@lumiastream/ui 0.5.2 → 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 +869 -466
- package/dist/se-import.d.ts +9 -3
- package/dist/se-import.js +868 -465
- 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":
|
|
@@ -7675,13 +7859,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7675
7859
|
const fontWeight = getField(settings, prefix, "font_weight") ?? 600;
|
|
7676
7860
|
const fontColor = getField(settings, prefix, "font_color") ?? "#FFFFFF";
|
|
7677
7861
|
const highlightColor = getField(settings, prefix, "font_color2") ?? "#32C3A6";
|
|
7678
|
-
const
|
|
7679
|
-
getField(settings, prefix, "message_font_size"),
|
|
7680
|
-
20
|
|
7681
|
-
);
|
|
7682
|
-
const messageFontFamily = getField(settings, prefix, "message_font") ?? fontFamily;
|
|
7683
|
-
const messageFontWeight = getField(settings, prefix, "message_font_weight") ?? 400;
|
|
7684
|
-
const messageFontColor = getField(settings, prefix, "message_font_color") ?? "#FFFFFF";
|
|
7862
|
+
const secondaryMessage = readSecondaryMessageConfig(settings, prefix, fontFamily);
|
|
7685
7863
|
const imageHref = absolutizeSLUrl(getField(settings, prefix, "image_href"));
|
|
7686
7864
|
const soundHref = absolutizeSLUrl(getField(settings, prefix, "sound_href"));
|
|
7687
7865
|
const soundVolume = getField(settings, prefix, "sound_volume") ?? 50;
|
|
@@ -7700,7 +7878,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7700
7878
|
accentColor: null,
|
|
7701
7879
|
highlightColor,
|
|
7702
7880
|
firstMessageTemplate: translateSeText(messageTemplate),
|
|
7703
|
-
secondMessageTemplate: "",
|
|
7881
|
+
secondMessageTemplate: secondaryMessage?.template ?? "",
|
|
7704
7882
|
thirdMessageTemplate: "",
|
|
7705
7883
|
showAvatar: false,
|
|
7706
7884
|
showAmount: true,
|
|
@@ -7723,12 +7901,10 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7723
7901
|
textShadow: "rgba(0, 0, 0, 0.8) 1px 1px 1px",
|
|
7724
7902
|
textAlign: "center"
|
|
7725
7903
|
},
|
|
7726
|
-
messageCss
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
fontWeight: messageFontWeight
|
|
7731
|
-
},
|
|
7904
|
+
// `messageCss` only matters when secondMessageTemplate is set;
|
|
7905
|
+
// leave it empty when SL didn't ship a secondary-message block
|
|
7906
|
+
// so Lumia's renderer falls back to its own default styling.
|
|
7907
|
+
messageCss: secondaryMessage?.css ?? {},
|
|
7732
7908
|
content: { value: translateSeText(messageTemplate) }
|
|
7733
7909
|
},
|
|
7734
7910
|
media: {
|
|
@@ -7763,14 +7939,39 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7763
7939
|
tts: {
|
|
7764
7940
|
enabled: getField(settings, prefix, "tts_enabled") ?? false,
|
|
7765
7941
|
voice: getField(settings, prefix, "tts_language") ?? "Brian",
|
|
7766
|
-
volume: clampVolume(
|
|
7767
|
-
getField(settings, prefix, "tts_volume") ?? 75
|
|
7768
|
-
),
|
|
7942
|
+
volume: clampVolume(getField(settings, prefix, "tts_volume") ?? 75),
|
|
7769
7943
|
minAmount: getField(settings, prefix, "tts_min_amount") ?? 0
|
|
7770
7944
|
},
|
|
7771
7945
|
variations: []
|
|
7772
7946
|
};
|
|
7773
7947
|
}
|
|
7948
|
+
var SECONDARY_MESSAGE_PREFIX_OVERRIDE = {
|
|
7949
|
+
sub: "resub"
|
|
7950
|
+
};
|
|
7951
|
+
function readSecondaryMessageConfig(settings, prefix, primaryFontFamily) {
|
|
7952
|
+
const secondaryPrefix = SECONDARY_MESSAGE_PREFIX_OVERRIDE[prefix] ?? prefix;
|
|
7953
|
+
const showKey = `show_${secondaryPrefix}_message`;
|
|
7954
|
+
const enabled = settings[showKey];
|
|
7955
|
+
if (enabled !== true) return null;
|
|
7956
|
+
const fontFamily = getField(settings, secondaryPrefix, "message_font") ?? primaryFontFamily;
|
|
7957
|
+
const fontSize = pxToNumber(getField(settings, secondaryPrefix, "message_font_size"), 20);
|
|
7958
|
+
const fontWeight = getField(settings, secondaryPrefix, "message_font_weight") ?? 400;
|
|
7959
|
+
const fontColor = getField(settings, secondaryPrefix, "message_font_color") ?? "#FFFFFF";
|
|
7960
|
+
return {
|
|
7961
|
+
// `{message}` is the SE/SL chat-message token (mapped to Lumia's
|
|
7962
|
+
// `{{message}}` in translate.ts). It resolves at render time from
|
|
7963
|
+
// the alert payload's `message` field — populated for every event
|
|
7964
|
+
// where SL ships a secondary-message line (donations, resubs,
|
|
7965
|
+
// cheers, charity, merch, etc.).
|
|
7966
|
+
template: translateSeText("{message}"),
|
|
7967
|
+
css: {
|
|
7968
|
+
fontFamily,
|
|
7969
|
+
fontSize,
|
|
7970
|
+
color: fontColor,
|
|
7971
|
+
fontWeight
|
|
7972
|
+
}
|
|
7973
|
+
};
|
|
7974
|
+
}
|
|
7774
7975
|
function clampVolume(slVolume) {
|
|
7775
7976
|
if (typeof slVolume !== "number" || !Number.isFinite(slVolume)) return 0.5;
|
|
7776
7977
|
return Math.max(0, Math.min(1, slVolume / 100));
|
|
@@ -7780,11 +7981,20 @@ function translateSLVariationCondition(v) {
|
|
|
7780
7981
|
const numericData = typeof data === "number" ? data : Number(data);
|
|
7781
7982
|
switch (v.condition) {
|
|
7782
7983
|
case "RANDOM":
|
|
7783
|
-
return {
|
|
7984
|
+
return {
|
|
7985
|
+
conditionType: "RANDOM",
|
|
7986
|
+
condition: Number.isFinite(numericData) ? numericData : 100
|
|
7987
|
+
};
|
|
7784
7988
|
case "MIN_BITS_USED":
|
|
7785
|
-
return {
|
|
7989
|
+
return {
|
|
7990
|
+
conditionType: "GREATER_NUMBER",
|
|
7991
|
+
condition: Number.isFinite(numericData) ? numericData : 0
|
|
7992
|
+
};
|
|
7786
7993
|
case "EXACT_BITS_USED":
|
|
7787
|
-
return {
|
|
7994
|
+
return {
|
|
7995
|
+
conditionType: "EQUAL_NUMBER",
|
|
7996
|
+
condition: Number.isFinite(numericData) ? numericData : 0
|
|
7997
|
+
};
|
|
7788
7998
|
case "MIN_MONTHS_SUBSCRIBED":
|
|
7789
7999
|
return {
|
|
7790
8000
|
conditionType: "SUBSCRIBED_MONTHS_GREATER",
|
|
@@ -7849,6 +8059,14 @@ function buildVariationEvent(v, parentBase) {
|
|
|
7849
8059
|
if (s.hideAnimation) inherited.animations.alertExitAnimation = s.hideAnimation;
|
|
7850
8060
|
if (s.layout) inherited.layout.value = translateLayout2(s.layout);
|
|
7851
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(),
|
|
7852
8070
|
name: v.name ?? "Variation",
|
|
7853
8071
|
on: v.paused !== true,
|
|
7854
8072
|
randomChance: 100,
|
|
@@ -7914,11 +8132,7 @@ function buildSLAlertBox(settings, options = {}) {
|
|
|
7914
8132
|
for (const [prefix, routing] of Object.entries(SL_EVENT_ROUTING)) {
|
|
7915
8133
|
const lumiaKeys = routing.pickProviderKeys ? alertBoxKeysFor(routing.pickProviderKeys, provider) : routing.keys ?? [];
|
|
7916
8134
|
if (lumiaKeys.length === 0) continue;
|
|
7917
|
-
const built = buildBaseAlertEvent(
|
|
7918
|
-
settings,
|
|
7919
|
-
prefix,
|
|
7920
|
-
DEFAULT_MESSAGES[prefix] ?? "{name}"
|
|
7921
|
-
);
|
|
8135
|
+
const built = buildBaseAlertEvent(settings, prefix, DEFAULT_MESSAGES[prefix] ?? "{name}");
|
|
7922
8136
|
if (!built) continue;
|
|
7923
8137
|
const variationKey = VARIATION_KEY_FOR_PREFIX[prefix];
|
|
7924
8138
|
const variations = variationKey ? settings[variationKey] : void 0;
|
|
@@ -7935,53 +8149,32 @@ function buildSLAlertBox(settings, options = {}) {
|
|
|
7935
8149
|
channelsImported.push(prefix);
|
|
7936
8150
|
if (firstEvent == null) firstEvent = built;
|
|
7937
8151
|
}
|
|
7938
|
-
const id = nanoid4();
|
|
7939
|
-
const layer = {
|
|
7940
|
-
id,
|
|
7941
|
-
state: { visible: true, locked: false },
|
|
7942
|
-
bounds: { x: 100, y: 100, width: 700, height: 600, scale: [1, 1] }
|
|
7943
|
-
};
|
|
7944
8152
|
const baseAlert = firstEvent ? stripEventOnlyFields(firstEvent) : {};
|
|
7945
|
-
const module = {
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
settings: { type: "alert", title: "Streamlabs Alerts", locked: false },
|
|
7950
|
-
lights: [],
|
|
7951
|
-
css: {},
|
|
7952
|
-
content: {},
|
|
7953
|
-
variables: {},
|
|
7954
|
-
events: {},
|
|
8153
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8154
|
+
type: "alert",
|
|
8155
|
+
title: "Streamlabs Alerts",
|
|
8156
|
+
bounds: { x: 100, y: 100, width: 700, height: 600 },
|
|
7955
8157
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7956
8158
|
alert: { ...baseAlert, events }
|
|
7957
|
-
};
|
|
8159
|
+
});
|
|
7958
8160
|
return { layer, module, channelsImported };
|
|
7959
8161
|
}
|
|
7960
8162
|
function stripEventOnlyFields(event) {
|
|
7961
|
-
const {
|
|
8163
|
+
const {
|
|
8164
|
+
on: _on,
|
|
8165
|
+
variations: _variations,
|
|
8166
|
+
matchEmptyCondition: _mec,
|
|
8167
|
+
...base
|
|
8168
|
+
} = event;
|
|
7962
8169
|
return base;
|
|
7963
8170
|
}
|
|
7964
8171
|
|
|
7965
8172
|
// src/sl-import/mappers/tip-jar.ts
|
|
7966
|
-
import { nanoid as nanoid5 } from "nanoid";
|
|
7967
|
-
function pxToNumber2(raw, fallback) {
|
|
7968
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
7969
|
-
if (typeof raw !== "string") return fallback;
|
|
7970
|
-
const trimmed = raw.trim();
|
|
7971
|
-
if (!trimmed) return fallback;
|
|
7972
|
-
if (trimmed.endsWith("px")) {
|
|
7973
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
7974
|
-
return Number.isFinite(n2) ? n2 : fallback;
|
|
7975
|
-
}
|
|
7976
|
-
const n = parseFloat(trimmed);
|
|
7977
|
-
return Number.isFinite(n) ? n : fallback;
|
|
7978
|
-
}
|
|
7979
8173
|
function buildSLTipJar(settings) {
|
|
7980
|
-
const id = nanoid5();
|
|
7981
8174
|
const backgroundColor = settings.background?.color ?? "transparent";
|
|
7982
8175
|
const textColor = settings.text?.color ?? "#FFFFFF";
|
|
7983
8176
|
const fontFamily = settings.text?.font ?? "Open Sans";
|
|
7984
|
-
const fontSize =
|
|
8177
|
+
const fontSize = pxToNumber(settings.text?.size, 32);
|
|
7985
8178
|
const types = settings.types ?? {};
|
|
7986
8179
|
const tipsConfig = types.tips ?? {};
|
|
7987
8180
|
const slEvents = {
|
|
@@ -7997,17 +8190,11 @@ function buildSLTipJar(settings) {
|
|
|
7997
8190
|
...TIPJAR_DEFAULT_MODULE.content.display,
|
|
7998
8191
|
showEventMessages: settings.text?.show !== false
|
|
7999
8192
|
};
|
|
8000
|
-
const layer = {
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
bounds: { x: 100, y: 100, width: 600, height: 700
|
|
8004
|
-
};
|
|
8005
|
-
const module = {
|
|
8006
|
-
id,
|
|
8193
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8194
|
+
type: "tipjar",
|
|
8195
|
+
title: "Streamlabs Tip Jar",
|
|
8196
|
+
bounds: { x: 100, y: 100, width: 600, height: 700 },
|
|
8007
8197
|
version: TIPJAR_DEFAULT_MODULE.version,
|
|
8008
|
-
loaded: true,
|
|
8009
|
-
settings: { type: "tipjar", title: "Streamlabs Tip Jar", locked: false },
|
|
8010
|
-
lights: [],
|
|
8011
8198
|
css: {
|
|
8012
8199
|
fontFamily,
|
|
8013
8200
|
fontSize,
|
|
@@ -8028,12 +8215,7 @@ function buildSLTipJar(settings) {
|
|
|
8028
8215
|
source: "streamlabs",
|
|
8029
8216
|
widgetType: "tip_jar",
|
|
8030
8217
|
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8031
|
-
// SL jar type doesn't have a 1:1 mapping to Lumia's preset
|
|
8032
|
-
// vocabulary (cup-01, cup-02, …). Stashed for review.
|
|
8033
8218
|
slJarType: settings.jar?.type ?? null,
|
|
8034
|
-
// SL tier coin tiers — Lumia's sprite tiers are per-event and
|
|
8035
|
-
// configured in the sprite editor; the user re-creates these
|
|
8036
|
-
// manually. Stored here so they're not lost.
|
|
8037
8219
|
slTipTiers: Array.isArray(tipsConfig.tiers) ? tipsConfig.tiers.map((t) => ({
|
|
8038
8220
|
minimumAmount: t.minimum_amount,
|
|
8039
8221
|
imageSrc: t.image_src ?? null
|
|
@@ -8041,15 +8223,12 @@ function buildSLTipJar(settings) {
|
|
|
8041
8223
|
slMinimumTipAmount: tipsConfig.minimum_amount ?? null,
|
|
8042
8224
|
slHadCustomHtml: settings.custom_html_enabled === true
|
|
8043
8225
|
}
|
|
8044
|
-
}
|
|
8045
|
-
|
|
8046
|
-
events: {}
|
|
8047
|
-
};
|
|
8226
|
+
}
|
|
8227
|
+
});
|
|
8048
8228
|
return { layer, module };
|
|
8049
8229
|
}
|
|
8050
8230
|
|
|
8051
8231
|
// src/sl-import/mappers/goal.ts
|
|
8052
|
-
import { nanoid as nanoid6 } from "nanoid";
|
|
8053
8232
|
var GOAL_SOURCE_MAP = {
|
|
8054
8233
|
follower_goal: "follower",
|
|
8055
8234
|
sub_goal: "subscriber",
|
|
@@ -8062,69 +8241,262 @@ var GOAL_TITLE_MAP = {
|
|
|
8062
8241
|
donation_goal: "Donation Goal",
|
|
8063
8242
|
bit_goal: "Bits Goal"
|
|
8064
8243
|
};
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
8072
|
-
return Number.isFinite(n2) ? n2 : fallback;
|
|
8073
|
-
}
|
|
8074
|
-
const n = parseFloat(trimmed);
|
|
8075
|
-
return Number.isFinite(n) ? n : fallback;
|
|
8076
|
-
}
|
|
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
|
+
};
|
|
8077
8250
|
function buildSLGoal(settings, widgetType) {
|
|
8078
|
-
const id = nanoid6();
|
|
8079
8251
|
const goalSource = GOAL_SOURCE_MAP[widgetType] ?? "follower";
|
|
8080
8252
|
const defaultTitle = GOAL_TITLE_MAP[widgetType] ?? "Goal";
|
|
8253
|
+
const currentTemplate = GOAL_CURRENT_TEMPLATE[widgetType] ?? "";
|
|
8254
|
+
const requiresReview = settings.custom_enabled === true;
|
|
8081
8255
|
const title = typeof settings.title === "string" ? settings.title : defaultTitle;
|
|
8082
8256
|
const goalAmount = typeof settings.goal === "number" ? settings.goal : 100;
|
|
8083
8257
|
const currentAmount = typeof settings.current === "number" ? settings.current : 0;
|
|
8084
8258
|
const startingAmount = typeof settings.starting_amount === "number" ? settings.starting_amount : 0;
|
|
8085
|
-
const endsAt = typeof settings.ends_at === "string" ? settings.ends_at :
|
|
8259
|
+
const endsAt = typeof settings.ends_at === "string" ? settings.ends_at : "";
|
|
8086
8260
|
const barColor = settings.bar_color ?? "#32C3A6";
|
|
8087
|
-
const
|
|
8261
|
+
const barBgColor = settings.bar_bg_color ?? "#181818";
|
|
8262
|
+
const widgetBgColor = settings.background_color ?? "transparent";
|
|
8088
8263
|
const textColor = settings.text_color ?? "#FFFFFF";
|
|
8089
8264
|
const barTextColor = settings.bar_text_color ?? textColor;
|
|
8090
8265
|
const fontFamily = settings.font ?? "Open Sans";
|
|
8091
|
-
const
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
version: 1,
|
|
8099
|
-
loaded: true,
|
|
8100
|
-
settings: { type: "goal", title, locked: false },
|
|
8101
|
-
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 },
|
|
8102
8273
|
css: {
|
|
8103
8274
|
fontFamily,
|
|
8104
8275
|
color: textColor,
|
|
8105
|
-
background:
|
|
8276
|
+
background: widgetBgColor,
|
|
8277
|
+
fontSize
|
|
8106
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.
|
|
8107
8283
|
content: {
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
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
|
|
8119
8356
|
},
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
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 };
|
|
8124
8494
|
}
|
|
8125
8495
|
|
|
8126
8496
|
// src/sl-import/sl-dispatch.ts
|
|
8127
|
-
|
|
8497
|
+
function buildSLDescription(widgetType, sourceUrl) {
|
|
8498
|
+
return buildImportDescription(`Imported from Streamlabs ${widgetType}`, sourceUrl);
|
|
8499
|
+
}
|
|
8128
8500
|
var GOAL_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
8129
8501
|
"follower_goal",
|
|
8130
8502
|
"sub_goal",
|
|
@@ -8132,8 +8504,6 @@ var GOAL_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
|
8132
8504
|
"bit_goal"
|
|
8133
8505
|
]);
|
|
8134
8506
|
var PLACEHOLDER_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
8135
|
-
"chat_box",
|
|
8136
|
-
"event_list",
|
|
8137
8507
|
"donation_ticker",
|
|
8138
8508
|
"stream_boss",
|
|
8139
8509
|
"credits",
|
|
@@ -8143,8 +8513,6 @@ var PLACEHOLDER_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
|
8143
8513
|
"streamlabels"
|
|
8144
8514
|
]);
|
|
8145
8515
|
var PLACEHOLDER_REASONS = {
|
|
8146
|
-
chat_box: "Lumia has a native chatbox module \u2014 set it up directly rather than importing the SL config.",
|
|
8147
|
-
event_list: "Lumia has a native eventlist module \u2014 set it up directly rather than importing the SL config.",
|
|
8148
8516
|
donation_ticker: "No native Lumia equivalent yet \u2014 imported as a placeholder text layer.",
|
|
8149
8517
|
stream_boss: "Lumia has a native streamboss module \u2014 set it up directly rather than importing the SL config.",
|
|
8150
8518
|
credits: "Lumia has a native credits module \u2014 set it up directly rather than importing the SL config.",
|
|
@@ -8153,19 +8521,14 @@ var PLACEHOLDER_REASONS = {
|
|
|
8153
8521
|
sub_train: "No native Lumia equivalent yet \u2014 imported as a placeholder text layer.",
|
|
8154
8522
|
streamlabels: "Use Lumia template variables (e.g. {{twitch_last_follower}}) inside a Text module instead of importing the SL streamlabels config."
|
|
8155
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.";
|
|
8156
8525
|
function stampImportMeta(module, widgetType, role, extra = {}) {
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
role,
|
|
8164
|
-
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8165
|
-
...existing,
|
|
8166
|
-
...extra
|
|
8167
|
-
}
|
|
8168
|
-
};
|
|
8526
|
+
stampImportMetaMerge(module, {
|
|
8527
|
+
source: "streamlabs",
|
|
8528
|
+
widgetType,
|
|
8529
|
+
role,
|
|
8530
|
+
...extra
|
|
8531
|
+
});
|
|
8169
8532
|
}
|
|
8170
8533
|
function buildPlaceholder(widgetType) {
|
|
8171
8534
|
const id = nanoid7();
|
|
@@ -8197,7 +8560,7 @@ function buildPlaceholder(widgetType) {
|
|
|
8197
8560
|
};
|
|
8198
8561
|
return { layer, module };
|
|
8199
8562
|
}
|
|
8200
|
-
function importStreamlabsWidget(response, widgetType) {
|
|
8563
|
+
function importStreamlabsWidget(response, widgetType, options = {}) {
|
|
8201
8564
|
if (!isSLWidgetConfigResponse(response)) {
|
|
8202
8565
|
throw new Error(
|
|
8203
8566
|
"Streamlabs response is missing the expected `settings` envelope. The widget may be private or the response format may have changed."
|
|
@@ -8247,9 +8610,61 @@ function importStreamlabsWidget(response, widgetType) {
|
|
|
8247
8610
|
coverage.mappings.push({
|
|
8248
8611
|
seType: `streamlabs:${widgetType}`,
|
|
8249
8612
|
lumiaType: "goal",
|
|
8250
|
-
status: "direct",
|
|
8613
|
+
status: built.requiresReview ? "partial" : "direct",
|
|
8251
8614
|
count: 1
|
|
8252
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
|
+
}
|
|
8253
8668
|
} else if (PLACEHOLDER_WIDGET_TYPES.has(widgetType)) {
|
|
8254
8669
|
const placeholder = buildPlaceholder(widgetType);
|
|
8255
8670
|
const reason = PLACEHOLDER_REASONS[widgetType] ?? "No native Lumia mapping yet.";
|
|
@@ -8298,7 +8713,7 @@ function importStreamlabsWidget(response, widgetType) {
|
|
|
8298
8713
|
uuid: "",
|
|
8299
8714
|
listen_id: "",
|
|
8300
8715
|
name: overlayName,
|
|
8301
|
-
description:
|
|
8716
|
+
description: buildSLDescription(widgetType, options.sourceUrl),
|
|
8302
8717
|
settings: {
|
|
8303
8718
|
metadata: { width: 1920, height: 1080 },
|
|
8304
8719
|
layers,
|
|
@@ -9860,7 +10275,12 @@ function SEImportWizard({
|
|
|
9860
10275
|
);
|
|
9861
10276
|
}
|
|
9862
10277
|
importedOverlays.push({
|
|
9863
|
-
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
|
+
}),
|
|
9864
10284
|
summary
|
|
9865
10285
|
});
|
|
9866
10286
|
}
|
|
@@ -9905,7 +10325,9 @@ function SEImportWizard({
|
|
|
9905
10325
|
"StreamElements returned a payload that doesn't look like an overlay bootstrap."
|
|
9906
10326
|
);
|
|
9907
10327
|
}
|
|
9908
|
-
const imported = importSEBootstrap(bootstrap
|
|
10328
|
+
const imported = importSEBootstrap(bootstrap, {
|
|
10329
|
+
sourceUrl: `https://streamelements.com/dashboard/overlays/${overlayId}/editor`
|
|
10330
|
+
});
|
|
9909
10331
|
setBatchImports([{ result: imported, summary }]);
|
|
9910
10332
|
setResult(imported);
|
|
9911
10333
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -9993,7 +10415,9 @@ function SEImportWizard({
|
|
|
9993
10415
|
"Streamlabs returned a response that does not look like a widget config payload."
|
|
9994
10416
|
);
|
|
9995
10417
|
}
|
|
9996
|
-
const imported = importStreamlabsWidget(raw, slParts.widgetType
|
|
10418
|
+
const imported = importStreamlabsWidget(raw, slParts.widgetType, {
|
|
10419
|
+
sourceUrl: url
|
|
10420
|
+
});
|
|
9997
10421
|
setBatchImports([]);
|
|
9998
10422
|
setResult(imported);
|
|
9999
10423
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10034,7 +10458,7 @@ function SEImportWizard({
|
|
|
10034
10458
|
"StreamElements returned a response that does not look like an Element widget payload."
|
|
10035
10459
|
);
|
|
10036
10460
|
}
|
|
10037
|
-
const imported = importElementOverlay(raw);
|
|
10461
|
+
const imported = importElementOverlay(raw, { sourceUrl: url });
|
|
10038
10462
|
setBatchImports([]);
|
|
10039
10463
|
setResult(imported);
|
|
10040
10464
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10082,7 +10506,7 @@ function SEImportWizard({
|
|
|
10082
10506
|
...parts,
|
|
10083
10507
|
proxyFetch: bindings.proxyFetch
|
|
10084
10508
|
});
|
|
10085
|
-
const imported = importSEBootstrap(bootstrap);
|
|
10509
|
+
const imported = importSEBootstrap(bootstrap, { sourceUrl: url });
|
|
10086
10510
|
setBatchImports([]);
|
|
10087
10511
|
setResult(imported);
|
|
10088
10512
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10741,7 +11165,7 @@ function extractErrorMessage(err) {
|
|
|
10741
11165
|
}
|
|
10742
11166
|
|
|
10743
11167
|
// src/se-import/element-dispatch.ts
|
|
10744
|
-
import {
|
|
11168
|
+
import { LumiaAlertValues as LumiaAlertValues3 } from "@lumiastream/lumia-types";
|
|
10745
11169
|
|
|
10746
11170
|
// src/se-import/element-types.ts
|
|
10747
11171
|
function isSEElementResponse(value) {
|
|
@@ -10985,34 +11409,8 @@ function translateAnimationName(name, fallback) {
|
|
|
10985
11409
|
if (PINNED_ANIMATION_MAP[name]) return PINNED_ANIMATION_MAP[name];
|
|
10986
11410
|
return name.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
|
|
10987
11411
|
}
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
if (typeof raw !== "string") return fallbackMs;
|
|
10991
|
-
const trimmed = raw.trim();
|
|
10992
|
-
if (!trimmed) return fallbackMs;
|
|
10993
|
-
if (trimmed.endsWith("ms")) {
|
|
10994
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
10995
|
-
return Number.isFinite(n2) ? n2 : fallbackMs;
|
|
10996
|
-
}
|
|
10997
|
-
if (trimmed.endsWith("s")) {
|
|
10998
|
-
const n2 = parseFloat(trimmed.slice(0, -1));
|
|
10999
|
-
return Number.isFinite(n2) ? n2 * 1e3 : fallbackMs;
|
|
11000
|
-
}
|
|
11001
|
-
const n = parseFloat(trimmed);
|
|
11002
|
-
return Number.isFinite(n) ? n : fallbackMs;
|
|
11003
|
-
}
|
|
11004
|
-
function parsePx2(raw) {
|
|
11005
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
11006
|
-
if (typeof raw !== "string") return NaN;
|
|
11007
|
-
const trimmed = raw.trim();
|
|
11008
|
-
if (!trimmed) return NaN;
|
|
11009
|
-
if (trimmed.endsWith("px")) {
|
|
11010
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
11011
|
-
return Number.isFinite(n2) ? n2 : NaN;
|
|
11012
|
-
}
|
|
11013
|
-
const n = parseFloat(trimmed);
|
|
11014
|
-
return Number.isFinite(n) ? n : NaN;
|
|
11015
|
-
}
|
|
11412
|
+
var parseAnimationDurationMs = parseDurationMs;
|
|
11413
|
+
var parsePx2 = (raw) => pxToNumber(raw, NaN);
|
|
11016
11414
|
function findFieldByType(fields, type) {
|
|
11017
11415
|
if (!fields) return void 0;
|
|
11018
11416
|
for (const f of Object.values(fields)) {
|
|
@@ -11088,6 +11486,47 @@ function buildAnimations(title) {
|
|
|
11088
11486
|
const visibleDurationMs = enterDelay + enterDuration + staticDuration + exitDuration;
|
|
11089
11487
|
return { animations, visibleDurationMs: visibleDurationMs || DEFAULT_DURATION_MS };
|
|
11090
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
|
+
}
|
|
11091
11530
|
function buildElementAlertEvent(state, options = {}) {
|
|
11092
11531
|
const compositeFields = state.settings?.compositeFields;
|
|
11093
11532
|
const titleField = findFieldByType(compositeFields, "text");
|
|
@@ -11105,6 +11544,31 @@ function buildElementAlertEvent(state, options = {}) {
|
|
|
11105
11544
|
const titleStyle = titleField?.style;
|
|
11106
11545
|
const highlightColor = titleField?.highlightedStyle?.color ?? null;
|
|
11107
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
|
+
}
|
|
11108
11572
|
const event = {
|
|
11109
11573
|
on: true,
|
|
11110
11574
|
// `'custom'` lowercase is load-bearing in Lumia's AlertBoxHandler —
|
|
@@ -11123,7 +11587,11 @@ function buildElementAlertEvent(state, options = {}) {
|
|
|
11123
11587
|
showBrandIcon: true
|
|
11124
11588
|
},
|
|
11125
11589
|
settings: { duration: visibleDurationMs },
|
|
11126
|
-
|
|
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 },
|
|
11127
11595
|
text: {
|
|
11128
11596
|
css: titleCss(titleStyle),
|
|
11129
11597
|
messageCss: {},
|
|
@@ -11145,44 +11613,13 @@ function buildElementAlertEvent(state, options = {}) {
|
|
|
11145
11613
|
},
|
|
11146
11614
|
variations: []
|
|
11147
11615
|
};
|
|
11148
|
-
|
|
11149
|
-
let bounds;
|
|
11150
|
-
if (style) {
|
|
11151
|
-
const x = parsePx2(style.left);
|
|
11152
|
-
const y = parsePx2(style.top);
|
|
11153
|
-
const width = parsePx2(style.width);
|
|
11154
|
-
const height = parsePx2(style.height);
|
|
11155
|
-
if (Number.isFinite(x) && Number.isFinite(y) && Number.isFinite(width)) {
|
|
11156
|
-
bounds = {
|
|
11157
|
-
x,
|
|
11158
|
-
y,
|
|
11159
|
-
width,
|
|
11160
|
-
// Height isn't always present on video Main Assets (the video
|
|
11161
|
-
// aspect-ratios itself from the source). Fall back to a
|
|
11162
|
-
// reasonable default that matches SE's preview row.
|
|
11163
|
-
height: Number.isFinite(height) ? height : Math.round(width * 0.75)
|
|
11164
|
-
};
|
|
11165
|
-
}
|
|
11166
|
-
}
|
|
11167
|
-
return { event, bounds };
|
|
11616
|
+
return { event, bounds: layerBounds };
|
|
11168
11617
|
}
|
|
11169
11618
|
|
|
11170
11619
|
// src/se-import/mappers/element-scene.ts
|
|
11171
|
-
import { nanoid as nanoid8 } from "nanoid";
|
|
11172
11620
|
var TEXT_FALLBACK = { width: 400, height: 50 };
|
|
11173
11621
|
var IMAGE_FALLBACK = { width: 300, height: 100 };
|
|
11174
|
-
|
|
11175
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
11176
|
-
if (typeof raw !== "string") return NaN;
|
|
11177
|
-
const trimmed = raw.trim();
|
|
11178
|
-
if (!trimmed) return NaN;
|
|
11179
|
-
if (trimmed.endsWith("px")) {
|
|
11180
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
11181
|
-
return Number.isFinite(n2) ? n2 : NaN;
|
|
11182
|
-
}
|
|
11183
|
-
const n = parseFloat(trimmed);
|
|
11184
|
-
return Number.isFinite(n) ? n : NaN;
|
|
11185
|
-
}
|
|
11622
|
+
var parsePx3 = (raw) => pxToNumber(raw, NaN);
|
|
11186
11623
|
function styleToBounds(style, type, canvas) {
|
|
11187
11624
|
const x = Number.isFinite(parsePx3(style?.left)) ? parsePx3(style?.left) : 0;
|
|
11188
11625
|
const y = Number.isFinite(parsePx3(style?.top)) ? parsePx3(style?.top) : 0;
|
|
@@ -11218,33 +11655,17 @@ function styleToBounds(style, type, canvas) {
|
|
|
11218
11655
|
}
|
|
11219
11656
|
return { x, y, width, height };
|
|
11220
11657
|
}
|
|
11221
|
-
function
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
11226
|
-
bounds: {
|
|
11227
|
-
x: bounds.x,
|
|
11228
|
-
y: bounds.y,
|
|
11229
|
-
width: bounds.width,
|
|
11230
|
-
height: bounds.height,
|
|
11231
|
-
scale: [1, 1],
|
|
11232
|
-
zIndex
|
|
11233
|
-
}
|
|
11234
|
-
};
|
|
11235
|
-
}
|
|
11236
|
-
function buildModule(id, type, title, content, css = {}) {
|
|
11237
|
-
return {
|
|
11238
|
-
id,
|
|
11239
|
-
version: 1,
|
|
11240
|
-
loaded: true,
|
|
11241
|
-
settings: { type, title, locked: false },
|
|
11242
|
-
lights: [],
|
|
11243
|
-
css,
|
|
11658
|
+
function buildChild(groupId, zIndex, bounds, type, title, content, css = {}) {
|
|
11659
|
+
const { layer, module } = buildModuleEnvelope({
|
|
11660
|
+
type,
|
|
11661
|
+
title,
|
|
11662
|
+
bounds,
|
|
11244
11663
|
content,
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11664
|
+
css,
|
|
11665
|
+
parentGroupId: groupId,
|
|
11666
|
+
zIndex
|
|
11667
|
+
});
|
|
11668
|
+
return { layer, module };
|
|
11248
11669
|
}
|
|
11249
11670
|
function textStyleToCss(style) {
|
|
11250
11671
|
const s = style ?? {};
|
|
@@ -11259,80 +11680,69 @@ function textStyleToCss(style) {
|
|
|
11259
11680
|
return out;
|
|
11260
11681
|
}
|
|
11261
11682
|
function mapCompositeField(name, field, groupId, zIndex, provider, canvas) {
|
|
11262
|
-
const id = nanoid8();
|
|
11263
11683
|
switch (field.type) {
|
|
11264
11684
|
case "video": {
|
|
11265
|
-
const bounds = styleToBounds(field.style, "video", canvas);
|
|
11266
|
-
const layer = buildLayer(id, groupId, bounds, zIndex);
|
|
11267
11685
|
const src = pickFieldMediaHref(field.media, "video/");
|
|
11268
11686
|
const volume = typeof field.volume === "number" ? field.volume : 1;
|
|
11269
|
-
|
|
11270
|
-
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
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
|
+
);
|
|
11277
11695
|
}
|
|
11278
11696
|
case "image": {
|
|
11279
|
-
const bounds = styleToBounds(field.style, "image", canvas);
|
|
11280
|
-
const layer = buildLayer(id, groupId, bounds, zIndex);
|
|
11281
11697
|
const src = pickFieldMediaHref(field.media, "image/");
|
|
11282
|
-
|
|
11283
|
-
|
|
11698
|
+
return buildChild(
|
|
11699
|
+
groupId,
|
|
11700
|
+
zIndex,
|
|
11701
|
+
styleToBounds(field.style, "image", canvas),
|
|
11702
|
+
"image",
|
|
11703
|
+
name,
|
|
11704
|
+
{ src }
|
|
11705
|
+
);
|
|
11284
11706
|
}
|
|
11285
11707
|
case "text": {
|
|
11286
|
-
const bounds = styleToBounds(field.style, "text", canvas);
|
|
11287
|
-
const layer = buildLayer(id, groupId, bounds, zIndex);
|
|
11288
11708
|
const raw = field.text?.[0]?.content ?? "";
|
|
11289
11709
|
const value = substituteElementTokens(raw, { provider });
|
|
11290
|
-
|
|
11291
|
-
|
|
11710
|
+
return buildChild(
|
|
11711
|
+
groupId,
|
|
11712
|
+
zIndex,
|
|
11713
|
+
styleToBounds(field.style, "text", canvas),
|
|
11292
11714
|
"text",
|
|
11293
11715
|
name,
|
|
11294
11716
|
{ value, highlightColor: "inherit" },
|
|
11295
11717
|
textStyleToCss(field.style)
|
|
11296
11718
|
);
|
|
11297
|
-
return { layer, module };
|
|
11298
11719
|
}
|
|
11299
11720
|
case "audio": {
|
|
11300
|
-
const layer = buildLayer(id, groupId, { x: 0, y: 0, width: 1, height: 1 }, zIndex);
|
|
11301
11721
|
const src = pickFieldMediaHref(field.media, "audio/");
|
|
11302
11722
|
const volume = typeof field.volume === "number" ? field.volume : 0.5;
|
|
11303
|
-
|
|
11304
|
-
|
|
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
|
+
);
|
|
11305
11731
|
}
|
|
11306
11732
|
default:
|
|
11307
11733
|
return null;
|
|
11308
11734
|
}
|
|
11309
11735
|
}
|
|
11310
11736
|
function buildElementScene(state, options) {
|
|
11311
|
-
const groupId = nanoid8();
|
|
11312
11737
|
const groupTitle = typeof state.displayName === "string" && state.displayName || state.referenceId || "Scene";
|
|
11313
|
-
const groupLayer = {
|
|
11314
|
-
id: groupId,
|
|
11738
|
+
const { id: groupId, layer: groupLayer, module: groupModule } = buildModuleEnvelope({
|
|
11315
11739
|
type: "group",
|
|
11316
|
-
|
|
11317
|
-
bounds: {
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
scale: [1, 1]
|
|
11323
|
-
},
|
|
11324
|
-
state: { visible: true, locked: false, expanded: false }
|
|
11325
|
-
};
|
|
11326
|
-
const groupModule = {
|
|
11327
|
-
id: groupId,
|
|
11328
|
-
loaded: true,
|
|
11329
|
-
settings: { type: "group", title: groupTitle },
|
|
11330
|
-
lights: [],
|
|
11331
|
-
css: {},
|
|
11332
|
-
content: {},
|
|
11333
|
-
variables: {},
|
|
11334
|
-
events: {}
|
|
11335
|
-
};
|
|
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
|
+
});
|
|
11336
11746
|
const children = [];
|
|
11337
11747
|
const fields = state.settings?.compositeFields ?? {};
|
|
11338
11748
|
let zIndex = 1;
|
|
@@ -11351,7 +11761,12 @@ function buildElementScene(state, options) {
|
|
|
11351
11761
|
}
|
|
11352
11762
|
|
|
11353
11763
|
// src/se-import/element-dispatch.ts
|
|
11354
|
-
|
|
11764
|
+
function buildElementDescription(widgetInstanceId, sourceUrl) {
|
|
11765
|
+
return buildImportDescription(
|
|
11766
|
+
`Imported from StreamElements Element widget ${widgetInstanceId}`,
|
|
11767
|
+
sourceUrl
|
|
11768
|
+
);
|
|
11769
|
+
}
|
|
11355
11770
|
function elementAlertKindToLumiaKeys(kind, provider) {
|
|
11356
11771
|
switch (kind) {
|
|
11357
11772
|
case "follower":
|
|
@@ -11370,9 +11785,9 @@ function elementAlertKindToLumiaKeys(kind, provider) {
|
|
|
11370
11785
|
return alertBoxKeysFor("charityCampaignDonation", provider);
|
|
11371
11786
|
case "subscriberGift":
|
|
11372
11787
|
case "communityGiftPurchase": {
|
|
11373
|
-
if (provider === "twitch") return [
|
|
11374
|
-
if (provider === "kick") return [
|
|
11375
|
-
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];
|
|
11376
11791
|
return alertBoxKeysFor("subscriber", provider);
|
|
11377
11792
|
}
|
|
11378
11793
|
default:
|
|
@@ -11387,7 +11802,7 @@ function buildCombinedAlertModule(alertStates, provider, canvas) {
|
|
|
11387
11802
|
for (const state of alertStates) {
|
|
11388
11803
|
const cls = classifyConfigState(state);
|
|
11389
11804
|
if (cls.kind !== "alert") continue;
|
|
11390
|
-
const { event, bounds: bounds2 } = buildElementAlertEvent(state, { provider });
|
|
11805
|
+
const { event, bounds: bounds2 } = buildElementAlertEvent(state, { provider, canvas });
|
|
11391
11806
|
const keys = elementAlertKindToLumiaKeys(cls.alertKind, provider);
|
|
11392
11807
|
if (keys.length === 0) continue;
|
|
11393
11808
|
for (const key of keys) {
|
|
@@ -11399,61 +11814,42 @@ function buildCombinedAlertModule(alertStates, provider, canvas) {
|
|
|
11399
11814
|
}
|
|
11400
11815
|
}
|
|
11401
11816
|
if (Object.keys(events).length === 0) return null;
|
|
11402
|
-
const id = nanoid9();
|
|
11403
11817
|
const bounds = firstBounds ?? {
|
|
11404
11818
|
x: Math.round(canvas.width * 0.6),
|
|
11405
11819
|
y: Math.round(canvas.height * 0.15),
|
|
11406
11820
|
width: 400,
|
|
11407
11821
|
height: 300
|
|
11408
11822
|
};
|
|
11409
|
-
const layer = {
|
|
11410
|
-
id,
|
|
11411
|
-
state: { visible: true, locked: false },
|
|
11412
|
-
bounds: {
|
|
11413
|
-
x: bounds.x,
|
|
11414
|
-
y: bounds.y,
|
|
11415
|
-
width: bounds.width,
|
|
11416
|
-
height: bounds.height,
|
|
11417
|
-
scale: [1, 1]
|
|
11418
|
-
}
|
|
11419
|
-
};
|
|
11420
11823
|
const baseAlert = firstEvent ? stripEventOnlyFields2(firstEvent) : {};
|
|
11421
|
-
const module = {
|
|
11422
|
-
|
|
11423
|
-
|
|
11424
|
-
|
|
11425
|
-
settings: { type: "alert", title: "Alerts (Element import)", locked: false },
|
|
11426
|
-
lights: [],
|
|
11427
|
-
css: {},
|
|
11428
|
-
content: {},
|
|
11429
|
-
variables: {},
|
|
11430
|
-
events: {},
|
|
11824
|
+
const { layer, module } = buildModuleEnvelope({
|
|
11825
|
+
type: "alert",
|
|
11826
|
+
title: "Alerts (Element import)",
|
|
11827
|
+
bounds,
|
|
11431
11828
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11432
11829
|
alert: { ...baseAlert, events }
|
|
11433
|
-
};
|
|
11830
|
+
});
|
|
11434
11831
|
return { layer, module };
|
|
11435
11832
|
}
|
|
11436
11833
|
function stripEventOnlyFields2(event) {
|
|
11437
|
-
const {
|
|
11834
|
+
const {
|
|
11835
|
+
on: _on,
|
|
11836
|
+
variations: _variations,
|
|
11837
|
+
matchEmptyCondition: _mec,
|
|
11838
|
+
...base
|
|
11839
|
+
} = event;
|
|
11438
11840
|
return base;
|
|
11439
11841
|
}
|
|
11440
11842
|
function stampImportMeta2(module, state, role) {
|
|
11441
|
-
module
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
displayName: state?.displayName,
|
|
11449
|
-
importedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11450
|
-
}
|
|
11451
|
-
};
|
|
11843
|
+
stampImportMetaMerge(module, {
|
|
11844
|
+
source: "streamelements-element",
|
|
11845
|
+
role,
|
|
11846
|
+
referenceId: state?.referenceId,
|
|
11847
|
+
categoryId: state?.categoryId,
|
|
11848
|
+
displayName: state?.displayName
|
|
11849
|
+
});
|
|
11452
11850
|
}
|
|
11453
|
-
function importElementOverlay(response) {
|
|
11454
|
-
const configData = parseElementConfigData(
|
|
11455
|
-
response.widgetInstanceConfigVersion.configData
|
|
11456
|
-
);
|
|
11851
|
+
function importElementOverlay(response, options = {}) {
|
|
11852
|
+
const configData = parseElementConfigData(response.widgetInstanceConfigVersion.configData);
|
|
11457
11853
|
if (!configData) {
|
|
11458
11854
|
throw new Error(
|
|
11459
11855
|
"StreamElements Element response carries an invalid configData payload. The widget may be corrupted or the response format may have changed."
|
|
@@ -11523,7 +11919,10 @@ function importElementOverlay(response) {
|
|
|
11523
11919
|
uuid: "",
|
|
11524
11920
|
listen_id: "",
|
|
11525
11921
|
name: response.widgetInstance.displayName ? `[SE Element] ${response.widgetInstance.displayName}` : `Imported from StreamElements Element (${response.widgetInstance.widgetInstanceId})`,
|
|
11526
|
-
description:
|
|
11922
|
+
description: buildElementDescription(
|
|
11923
|
+
response.widgetInstance.widgetInstanceId,
|
|
11924
|
+
options.sourceUrl
|
|
11925
|
+
),
|
|
11527
11926
|
settings: {
|
|
11528
11927
|
metadata: { width: canvas.width, height: canvas.height },
|
|
11529
11928
|
layers,
|
|
@@ -11537,7 +11936,7 @@ function importElementOverlay(response) {
|
|
|
11537
11936
|
}
|
|
11538
11937
|
|
|
11539
11938
|
// src/se-import/index.ts
|
|
11540
|
-
var
|
|
11939
|
+
var IMPORT_META_KEY2 = "importMeta";
|
|
11541
11940
|
var REVIEW_REASONS = {
|
|
11542
11941
|
"se-widget-bit-boss": "No native Lumia equivalent \u2014 bit boss fight bar with HP/damage states.",
|
|
11543
11942
|
// `se-widget-hype-cup` intentionally omitted — it now routes to the native
|
|
@@ -11567,6 +11966,10 @@ function reasonFor(seType, status, flaggedOff) {
|
|
|
11567
11966
|
if (flaggedOff && FLAG_OFF_REASONS[seType]) return FLAG_OFF_REASONS[seType];
|
|
11568
11967
|
return REVIEW_REASONS[seType] ?? (status === "template" ? "Imported as a generic template stub." : "No native mapping yet \u2014 imported as a labelled text placeholder.");
|
|
11569
11968
|
}
|
|
11969
|
+
function buildSEBootstrapDescription(overlayId, sourceUrl) {
|
|
11970
|
+
const head = overlayId ? `Imported from StreamElements overlay ${overlayId}` : "Imported from StreamElements";
|
|
11971
|
+
return buildImportDescription(head, sourceUrl);
|
|
11972
|
+
}
|
|
11570
11973
|
function extractSEOverlayId(input) {
|
|
11571
11974
|
const trimmed = input.trim();
|
|
11572
11975
|
const m = trimmed.match(/[0-9a-f]{24}/i);
|
|
@@ -11621,7 +12024,7 @@ function isSEBootstrap(value) {
|
|
|
11621
12024
|
const o = v.overlay;
|
|
11622
12025
|
return Array.isArray(o.widgets);
|
|
11623
12026
|
}
|
|
11624
|
-
function importSEBootstrap(bootstrap) {
|
|
12027
|
+
function importSEBootstrap(bootstrap, options = {}) {
|
|
11625
12028
|
const seOverlay = bootstrap.overlay;
|
|
11626
12029
|
const widgets = seOverlay?.widgets ?? [];
|
|
11627
12030
|
const coverage = {
|
|
@@ -11644,7 +12047,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11644
12047
|
if (w.type !== "se-widget-group") continue;
|
|
11645
12048
|
const uid = w.variables?.uid;
|
|
11646
12049
|
if (typeof uid !== "string") continue;
|
|
11647
|
-
const lumiaGroupId =
|
|
12050
|
+
const lumiaGroupId = nanoid8();
|
|
11648
12051
|
seUidToLumiaGroupId[uid] = lumiaGroupId;
|
|
11649
12052
|
groupWidgetByUid[uid] = w;
|
|
11650
12053
|
}
|
|
@@ -11683,7 +12086,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11683
12086
|
lights: [],
|
|
11684
12087
|
css: {},
|
|
11685
12088
|
content: {
|
|
11686
|
-
[
|
|
12089
|
+
[IMPORT_META_KEY2]: {
|
|
11687
12090
|
source: "streamelements",
|
|
11688
12091
|
widgetType: w.type,
|
|
11689
12092
|
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -11721,7 +12124,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11721
12124
|
if (result.status === "placeholder" || result.status === "template") {
|
|
11722
12125
|
module.content = {
|
|
11723
12126
|
...module.content ?? {},
|
|
11724
|
-
[
|
|
12127
|
+
[IMPORT_META_KEY2]: {
|
|
11725
12128
|
source: "streamelements",
|
|
11726
12129
|
widgetType: w.type,
|
|
11727
12130
|
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -11761,7 +12164,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11761
12164
|
uuid: "",
|
|
11762
12165
|
listen_id: "",
|
|
11763
12166
|
name: seOverlay?.name ? `[SE] ${seOverlay.name}` : `Imported from StreamElements (${seOverlay?._id ?? ""})`,
|
|
11764
|
-
description: seOverlay?._id
|
|
12167
|
+
description: buildSEBootstrapDescription(seOverlay?._id, options.sourceUrl),
|
|
11765
12168
|
settings: {
|
|
11766
12169
|
metadata: {
|
|
11767
12170
|
width: seOverlay?.settings?.width ?? 1920,
|
|
@@ -11809,7 +12212,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11809
12212
|
bounds: existingLayer.bounds,
|
|
11810
12213
|
state: existingLayer.state
|
|
11811
12214
|
};
|
|
11812
|
-
const importMeta2 = existing2.content?.[
|
|
12215
|
+
const importMeta2 = existing2.content?.[IMPORT_META_KEY2];
|
|
11813
12216
|
const mergedLights = (existing2.lights?.length ?? 0) > 0 ? existing2.lights : transplant.module.lights;
|
|
11814
12217
|
const mergedEvents = existing2.events && Object.keys(existing2.events).length > 0 ? { ...transplant.module.events, ...existing2.events } : transplant.module.events;
|
|
11815
12218
|
const mergedVariables = existing2.variables && Object.keys(existing2.variables).length > 0 ? { ...transplant.module.variables, ...existing2.variables } : transplant.module.variables;
|
|
@@ -11821,7 +12224,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11821
12224
|
variables: mergedVariables,
|
|
11822
12225
|
content: {
|
|
11823
12226
|
...transplant.module.content ?? {},
|
|
11824
|
-
[
|
|
12227
|
+
[IMPORT_META_KEY2]: importMeta2
|
|
11825
12228
|
}
|
|
11826
12229
|
};
|
|
11827
12230
|
const rootOldNewId = transplant.layer.id;
|
|
@@ -11849,7 +12252,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11849
12252
|
const existing = modules[moduleId];
|
|
11850
12253
|
const generated = payload;
|
|
11851
12254
|
if (!existing || !generated) return result;
|
|
11852
|
-
const importMeta = existing.content?.[
|
|
12255
|
+
const importMeta = existing.content?.[IMPORT_META_KEY2];
|
|
11853
12256
|
const replaced = {
|
|
11854
12257
|
...existing,
|
|
11855
12258
|
settings: { ...existing.settings ?? {}, type: "custom" },
|
|
@@ -11863,7 +12266,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11863
12266
|
data: parseLooseJson(generated.data) ?? {},
|
|
11864
12267
|
configs: parseLooseJson(generated.configs) ?? [],
|
|
11865
12268
|
flavor: "ai-generated",
|
|
11866
|
-
[
|
|
12269
|
+
[IMPORT_META_KEY2]: importMeta
|
|
11867
12270
|
}
|
|
11868
12271
|
};
|
|
11869
12272
|
modules[moduleId] = replaced;
|