@lumiastream/ui 0.2.8-alpha.12 → 0.2.8-alpha.13
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/index.js +240 -45
- package/dist/se-import.js +240 -45
- package/package.json +131 -131
package/dist/index.js
CHANGED
|
@@ -3341,11 +3341,11 @@ var LUMIA_DEFAULT_SIZES = {
|
|
|
3341
3341
|
audio: { width: 200, height: 200 },
|
|
3342
3342
|
slideshow: { width: 400, height: 220 },
|
|
3343
3343
|
alert: { width: 700, height: 600 },
|
|
3344
|
-
//
|
|
3345
|
-
// in" sublabel
|
|
3346
|
-
//
|
|
3347
|
-
//
|
|
3348
|
-
goal: { width: 740, height:
|
|
3344
|
+
// Sized for the SE-style slim layout — title (~24px line) + tight gap +
|
|
3345
|
+
// 1.7em bar + optional "Ends in" sublabel collapses to ~70-85 px. 90 gives
|
|
3346
|
+
// a small safety margin for larger fonts without leaving dead space in the
|
|
3347
|
+
// editor canvas (which doesn't honor the layer's `autoHeight: true`).
|
|
3348
|
+
goal: { width: 740, height: 90 },
|
|
3349
3349
|
timer: { width: 740, height: 80 },
|
|
3350
3350
|
chatbox: { width: 375, height: 470 },
|
|
3351
3351
|
eventlist: { width: 375, height: 470 },
|
|
@@ -3382,10 +3382,20 @@ function translateVariationCondition(seType, seCondition, requirement) {
|
|
|
3382
3382
|
return { conditionType: "RANDOM", condition: 100 };
|
|
3383
3383
|
}
|
|
3384
3384
|
var LUMIA_LAYOUTS = /* @__PURE__ */ new Set(["column", "row", "onlyImage", "onlyText", "imageOver", "textOver"]);
|
|
3385
|
+
var SE_LAYOUT_ALIASES = {
|
|
3386
|
+
behind: "textOver"
|
|
3387
|
+
};
|
|
3385
3388
|
function translateLayout(seLayout) {
|
|
3386
|
-
if (seLayout
|
|
3389
|
+
if (!seLayout) return "column";
|
|
3390
|
+
const alias = SE_LAYOUT_ALIASES[seLayout];
|
|
3391
|
+
if (alias) return alias;
|
|
3392
|
+
if (LUMIA_LAYOUTS.has(seLayout)) return seLayout;
|
|
3387
3393
|
return "column";
|
|
3388
3394
|
}
|
|
3395
|
+
function seLayoutUsesPushText(seLayout) {
|
|
3396
|
+
if (!seLayout) return true;
|
|
3397
|
+
return seLayout !== "behind";
|
|
3398
|
+
}
|
|
3389
3399
|
|
|
3390
3400
|
// src/se-import/mappers/build.ts
|
|
3391
3401
|
import { nanoid } from "nanoid";
|
|
@@ -3596,7 +3606,7 @@ function buildAlertEvent(seEvent, seEventType) {
|
|
|
3596
3606
|
const importedTextShadow = css["text-shadow"] ?? "rgba(0, 0, 0, 0.8) 1px 1px 1px";
|
|
3597
3607
|
const textShadow = shadowEnabled ? importedTextShadow : "none";
|
|
3598
3608
|
const marginTopRaw = Number(css["margin-top"]);
|
|
3599
|
-
const pushTextUp = Number.isFinite(marginTopRaw) ? -marginTopRaw : 0;
|
|
3609
|
+
const pushTextUp = seLayoutUsesPushText(seEvent.layout) && Number.isFinite(marginTopRaw) ? -marginTopRaw : 0;
|
|
3600
3610
|
const variations = (seEvent.variations ?? []).map((variation) => buildAlertVariation(variation, seEventType, seEvent)).filter((v) => v != null);
|
|
3601
3611
|
const defaultDuration = (seEventType && SE_DEFAULT_DURATION_BY_EVENT[seEventType]) ?? 8;
|
|
3602
3612
|
return {
|
|
@@ -3726,25 +3736,52 @@ function deepMergeSeSettings(parent, variation) {
|
|
|
3726
3736
|
}
|
|
3727
3737
|
return out;
|
|
3728
3738
|
}
|
|
3739
|
+
function pickBaseAlertFields(event) {
|
|
3740
|
+
const { on: _on, variations: _variations, matchEmptyCondition: _mec, ...base } = event;
|
|
3741
|
+
return base;
|
|
3742
|
+
}
|
|
3729
3743
|
function mapAlertBox(widget, opts = {}) {
|
|
3730
3744
|
const v = widget.variables ?? {};
|
|
3731
3745
|
const events = {};
|
|
3732
3746
|
const eventKeys = opts.onlyEvents ?? ["follower", "subscriber", "tip", "cheer", "raid", "merch", "purchase", "charityCampaignDonation"];
|
|
3747
|
+
let firstEvent = null;
|
|
3733
3748
|
for (const seKey of eventKeys) {
|
|
3734
3749
|
const ev = v[seKey];
|
|
3735
3750
|
if (!ev || typeof ev !== "object") continue;
|
|
3736
3751
|
const lumiaAlert = SE_EVENT_TO_LUMIA_ALERT[seKey];
|
|
3737
3752
|
if (!lumiaAlert) continue;
|
|
3738
|
-
|
|
3753
|
+
const built = buildAlertEvent(ev, seKey);
|
|
3754
|
+
events[lumiaAlert] = built;
|
|
3755
|
+
if (firstEvent == null) firstEvent = built;
|
|
3739
3756
|
}
|
|
3740
|
-
|
|
3757
|
+
const baseAlert = firstEvent ? pickBaseAlertFields(firstEvent) : {};
|
|
3758
|
+
return buildUnit(widget, "alert", { alert: { ...baseAlert, events } });
|
|
3741
3759
|
}
|
|
3742
3760
|
function mapSingleAlert(widget, lumiaAlertKey) {
|
|
3743
3761
|
const v = widget.variables ?? {};
|
|
3762
|
+
const topText = widget.text;
|
|
3763
|
+
const merged = { ...v };
|
|
3764
|
+
if (topText) {
|
|
3765
|
+
const inner = v.text ?? {};
|
|
3766
|
+
const innerCss = inner.css ?? {};
|
|
3767
|
+
const topCss = topText.css ?? {};
|
|
3768
|
+
merged.text = {
|
|
3769
|
+
...inner,
|
|
3770
|
+
message: inner.message ?? topText.value ?? "",
|
|
3771
|
+
enableShadow: inner.enableShadow ?? topText.enableShadow,
|
|
3772
|
+
// Top-level SE CSS is the source of truth for Extra Life / DonorDrive
|
|
3773
|
+
// (which omit `variables.text` entirely). For Tiltify both are populated
|
|
3774
|
+
// with the same values; letting the nested `variables.text.css` win
|
|
3775
|
+
// preserves any per-event overrides the streamer might have set.
|
|
3776
|
+
css: { ...topCss, ...innerCss }
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
const built = buildAlertEvent(merged);
|
|
3744
3780
|
const events = {
|
|
3745
|
-
[lumiaAlertKey]:
|
|
3781
|
+
[lumiaAlertKey]: built
|
|
3746
3782
|
};
|
|
3747
|
-
|
|
3783
|
+
const baseAlert = pickBaseAlertFields(built);
|
|
3784
|
+
return buildUnit(widget, "alert", { alert: { ...baseAlert, events } });
|
|
3748
3785
|
}
|
|
3749
3786
|
|
|
3750
3787
|
// src/se-import/mappers/goal.ts
|
|
@@ -3760,9 +3797,17 @@ function currentForListener(listener) {
|
|
|
3760
3797
|
if (listener.startsWith("merch-")) return "{{fourthwall_total_order_count}}";
|
|
3761
3798
|
return "0";
|
|
3762
3799
|
}
|
|
3800
|
+
function charityGoalVariables(widgetType) {
|
|
3801
|
+
if (widgetType === "se-widget-tiltify-goal") return { current: "{{tiltify_total_raised=0}}", targetGoal: "{{tiltify_goal_amount=100}}" };
|
|
3802
|
+
if (widgetType === "se-widget-extralife-goal") return { current: "{{extralife_total_raised=0}}", targetGoal: "{{extralife_goal_amount=100}}" };
|
|
3803
|
+
if (widgetType === "se-widget-donor-drive-goal") return { current: "{{donordrive_total_raised=0}}", targetGoal: "{{donordrive_goal_amount=100}}" };
|
|
3804
|
+
return null;
|
|
3805
|
+
}
|
|
3763
3806
|
function mapGoal(widget) {
|
|
3764
3807
|
const v = widget.variables ?? {};
|
|
3765
3808
|
const listener = v.goalListener ?? (typeof widget.listener === "string" ? widget.listener : null);
|
|
3809
|
+
const charity = charityGoalVariables(widget.type);
|
|
3810
|
+
const seTextCss = widget.text?.css ?? {};
|
|
3766
3811
|
return buildUnit(widget, "goal", {
|
|
3767
3812
|
content: {
|
|
3768
3813
|
version: 1,
|
|
@@ -3774,11 +3819,13 @@ function mapGoal(widget) {
|
|
|
3774
3819
|
label: translateSeText(v.title ?? "Goal"),
|
|
3775
3820
|
subLabel: "",
|
|
3776
3821
|
// The Goal module renders this template literal with {{current}} + {{goal}} substituted.
|
|
3777
|
-
|
|
3822
|
+
// Charity goals track donation amounts — prefix `$` so the rendered bar reads
|
|
3823
|
+
// "$0 / $100" the way SE's charity goals do, instead of bare integers.
|
|
3824
|
+
display: charity ? "${{current}} / ${{goal}}" : "{{current}} / {{goal}}",
|
|
3778
3825
|
// `current` is a template variable reference (resolved at render time from session variables).
|
|
3779
3826
|
// `targetGoal` is the numeric ceiling. Both required by Goal/index.tsx:28-29.
|
|
3780
|
-
current: currentForListener(listener),
|
|
3781
|
-
targetGoal: String(v.goalAmount ?? 100),
|
|
3827
|
+
current: charity ? charity.current : currentForListener(listener),
|
|
3828
|
+
targetGoal: charity ? charity.targetGoal : String(v.goalAmount ?? 100),
|
|
3782
3829
|
image: "",
|
|
3783
3830
|
audio: { decrement: "", increment: "", goal: "", goalFailed: "", volume: 1 },
|
|
3784
3831
|
// `null` (rather than `''`) is the cleaner contract — Goal/index.tsx:11's
|
|
@@ -3805,13 +3852,13 @@ function mapGoal(widget) {
|
|
|
3805
3852
|
// `content.border` and `content.borderRadius`. Writing them to
|
|
3806
3853
|
// module.css just plopped useless transparent-0px rules on the
|
|
3807
3854
|
// outer .overlay-module wrapper.
|
|
3808
|
-
lineHeight: 1,
|
|
3809
|
-
fontSize: 30,
|
|
3810
|
-
textAlign: "center",
|
|
3811
|
-
fontFamily: "Roboto",
|
|
3812
|
-
fontWeight: "bold",
|
|
3813
|
-
color: "#ffffff",
|
|
3814
|
-
textShadow: "rgb(0, 0, 0) 1px 1px 1px",
|
|
3855
|
+
lineHeight: seTextCss["line-height"] ?? 1,
|
|
3856
|
+
fontSize: seTextCss["font-size"] ?? 30,
|
|
3857
|
+
textAlign: seTextCss["text-align"] ?? "center",
|
|
3858
|
+
fontFamily: seTextCss["font-family"] ?? "Roboto",
|
|
3859
|
+
fontWeight: seTextCss["font-weight"] ?? "bold",
|
|
3860
|
+
color: seTextCss.color ?? "#ffffff",
|
|
3861
|
+
textShadow: seTextCss["text-shadow"] ?? "rgb(0, 0, 0) 1px 1px 1px",
|
|
3815
3862
|
background: "transparent"
|
|
3816
3863
|
}
|
|
3817
3864
|
});
|
|
@@ -4070,33 +4117,143 @@ function mapEventList(widget) {
|
|
|
4070
4117
|
}
|
|
4071
4118
|
});
|
|
4072
4119
|
}
|
|
4073
|
-
var
|
|
4120
|
+
var SE_CREDITS_EVENTS_TO_SHOW = {
|
|
4074
4121
|
mods: false,
|
|
4075
4122
|
subscribers: true,
|
|
4076
4123
|
gifts: true,
|
|
4077
|
-
donations:
|
|
4078
|
-
purchases:
|
|
4079
|
-
bits:
|
|
4080
|
-
kicks:
|
|
4081
|
-
raids:
|
|
4082
|
-
hosts:
|
|
4083
|
-
superstickers:
|
|
4084
|
-
superchats:
|
|
4085
|
-
redemptions:
|
|
4086
|
-
stars:
|
|
4087
|
-
fans:
|
|
4124
|
+
donations: false,
|
|
4125
|
+
purchases: false,
|
|
4126
|
+
bits: false,
|
|
4127
|
+
kicks: false,
|
|
4128
|
+
raids: false,
|
|
4129
|
+
hosts: false,
|
|
4130
|
+
superstickers: false,
|
|
4131
|
+
superchats: false,
|
|
4132
|
+
redemptions: false,
|
|
4133
|
+
stars: false,
|
|
4134
|
+
fans: false,
|
|
4088
4135
|
shares: false,
|
|
4089
|
-
spells:
|
|
4136
|
+
spells: false,
|
|
4090
4137
|
likes: false,
|
|
4091
|
-
followers:
|
|
4138
|
+
followers: false,
|
|
4092
4139
|
others: false,
|
|
4093
|
-
topGifts:
|
|
4094
|
-
topBits:
|
|
4095
|
-
topKicks:
|
|
4096
|
-
topDonations:
|
|
4097
|
-
topSuperstickers:
|
|
4098
|
-
topSuperchats:
|
|
4099
|
-
topRedemptions:
|
|
4140
|
+
topGifts: false,
|
|
4141
|
+
topBits: false,
|
|
4142
|
+
topKicks: false,
|
|
4143
|
+
topDonations: false,
|
|
4144
|
+
topSuperstickers: false,
|
|
4145
|
+
topSuperchats: false,
|
|
4146
|
+
topRedemptions: false
|
|
4147
|
+
};
|
|
4148
|
+
var CREDITS_DEFAULT_SECTION_ORDER = [
|
|
4149
|
+
"topGifts",
|
|
4150
|
+
"topBits",
|
|
4151
|
+
"topKicks",
|
|
4152
|
+
"topDonations",
|
|
4153
|
+
"topSuperstickers",
|
|
4154
|
+
"topSuperchats",
|
|
4155
|
+
"topRedemptions",
|
|
4156
|
+
"subscribers",
|
|
4157
|
+
"gifts",
|
|
4158
|
+
"followers",
|
|
4159
|
+
"donations",
|
|
4160
|
+
"bits",
|
|
4161
|
+
"kicks",
|
|
4162
|
+
"raids",
|
|
4163
|
+
"hosts",
|
|
4164
|
+
"superstickers",
|
|
4165
|
+
"superchats",
|
|
4166
|
+
"redemptions",
|
|
4167
|
+
"others"
|
|
4168
|
+
];
|
|
4169
|
+
var CREDITS_DEFAULT_TOP_LIMITS = {
|
|
4170
|
+
topGifts: 5,
|
|
4171
|
+
topBits: 5,
|
|
4172
|
+
topKicks: 5,
|
|
4173
|
+
topDonations: 5,
|
|
4174
|
+
topSuperstickers: 5,
|
|
4175
|
+
topSuperchats: 5,
|
|
4176
|
+
topRedemptions: 5
|
|
4177
|
+
};
|
|
4178
|
+
var CREDITS_DEFAULT_EVENT_NAMES = {
|
|
4179
|
+
mods: "Mods (Total {{amount}})",
|
|
4180
|
+
topGifts: "Top Gifters",
|
|
4181
|
+
topBits: "Top Cheerers",
|
|
4182
|
+
topKicks: "Top Kicks",
|
|
4183
|
+
topDonations: "Top Donators",
|
|
4184
|
+
topSuperstickers: "Top Super Stickers",
|
|
4185
|
+
topSuperchats: "Top Super Chatters",
|
|
4186
|
+
topRedemptions: "Top Redeemers",
|
|
4187
|
+
subscribers: "Subscribers (Total {{amount}})",
|
|
4188
|
+
gifts: "Gifts (Total {{amount}})",
|
|
4189
|
+
donations: "Donations (Total {{amount}})",
|
|
4190
|
+
purchases: "Purchases (Total {{amount}})",
|
|
4191
|
+
bits: "Cheers (Total {{amount}})",
|
|
4192
|
+
kicks: "Kicks (Total {{amount}})",
|
|
4193
|
+
superstickers: "Super Stickers (Total {{amount}})",
|
|
4194
|
+
superchats: "Super Chatters (Total {{amount}})",
|
|
4195
|
+
redemptions: "Redemptions (Total {{amount}})",
|
|
4196
|
+
stars: "Stars (Total {{amount}})",
|
|
4197
|
+
fans: "Fans (Total {{amount}})",
|
|
4198
|
+
shares: "Shares (Total {{amount}})",
|
|
4199
|
+
raids: "Raids (Total {{amount}})",
|
|
4200
|
+
hosts: "Hosts (Total {{amount}})",
|
|
4201
|
+
spells: "Spells (Total {{amount}})",
|
|
4202
|
+
retweets: "Retweets (Total {{amount}})",
|
|
4203
|
+
likes: "Likes (Total {{amount}})",
|
|
4204
|
+
followers: "Followers (Total {{amount}})",
|
|
4205
|
+
others: "Other (Total {{amount}})"
|
|
4206
|
+
};
|
|
4207
|
+
var CREDITS_DEFAULT_PREFIXES = {
|
|
4208
|
+
mods: "x",
|
|
4209
|
+
subscribers: "x",
|
|
4210
|
+
gifts: "x",
|
|
4211
|
+
donations: "x",
|
|
4212
|
+
purchases: "x",
|
|
4213
|
+
bits: "x",
|
|
4214
|
+
kicks: "x",
|
|
4215
|
+
superstickers: "x",
|
|
4216
|
+
superchats: "x",
|
|
4217
|
+
redemptions: "x",
|
|
4218
|
+
stars: "x",
|
|
4219
|
+
fans: "x",
|
|
4220
|
+
shares: "x",
|
|
4221
|
+
raids: "x",
|
|
4222
|
+
hosts: "x",
|
|
4223
|
+
spells: "x",
|
|
4224
|
+
retweets: "x",
|
|
4225
|
+
likes: "x",
|
|
4226
|
+
followers: "",
|
|
4227
|
+
others: ""
|
|
4228
|
+
};
|
|
4229
|
+
var CREDITS_DEFAULT_TEMPLATES = {
|
|
4230
|
+
mods: "{{username}}",
|
|
4231
|
+
subscribers: "{{username}} x{{amount}}",
|
|
4232
|
+
gifts: "{{username}} x{{amount}}",
|
|
4233
|
+
donations: "{{username}} x{{amount}}",
|
|
4234
|
+
purchases: "{{username}} x{{amount}}",
|
|
4235
|
+
bits: "{{username}} x{{amount}}",
|
|
4236
|
+
kicks: "{{username}} x{{amount}}",
|
|
4237
|
+
raids: "{{username}} x{{amount}}",
|
|
4238
|
+
hosts: "{{username}} x{{amount}}",
|
|
4239
|
+
superstickers: "{{username}} x{{amount}}",
|
|
4240
|
+
superchats: "{{username}} x{{amount}}",
|
|
4241
|
+
redemptions: "{{username}} x{{amount}}",
|
|
4242
|
+
stars: "{{username}} x{{amount}}",
|
|
4243
|
+
fans: "{{username}} x{{amount}}",
|
|
4244
|
+
shares: "{{username}}",
|
|
4245
|
+
spells: "{{username}} x{{amount}}",
|
|
4246
|
+
retweets: "{{username}}",
|
|
4247
|
+
likes: "{{username}}",
|
|
4248
|
+
followers: "{{username}}",
|
|
4249
|
+
others: "{{username}} x{{amount}}",
|
|
4250
|
+
topGifts: "{{username}} x{{amount}}",
|
|
4251
|
+
topBits: "{{username}} x{{amount}}",
|
|
4252
|
+
topKicks: "{{username}} x{{amount}}",
|
|
4253
|
+
topDonations: "{{username}} x{{amount}}",
|
|
4254
|
+
topSuperstickers: "{{username}} x{{amount}}",
|
|
4255
|
+
topSuperchats: "{{username}} x{{amount}}",
|
|
4256
|
+
topRedemptions: "{{username}} x{{amount}}"
|
|
4100
4257
|
};
|
|
4101
4258
|
function mapCredits(widget) {
|
|
4102
4259
|
const v = widget.variables ?? {};
|
|
@@ -4104,20 +4261,53 @@ function mapCredits(widget) {
|
|
|
4104
4261
|
const reverseFlow = v.direction === "bottom";
|
|
4105
4262
|
return buildUnit(widget, "credits", {
|
|
4106
4263
|
content: {
|
|
4264
|
+
version: 1,
|
|
4107
4265
|
type: "basic",
|
|
4108
4266
|
title: "Stream Credits",
|
|
4109
|
-
|
|
4110
|
-
|
|
4267
|
+
titleColor: "#ffffff",
|
|
4268
|
+
subtitle: "A massive thanks to everyone below",
|
|
4269
|
+
subtitleColor: "#ffffff",
|
|
4270
|
+
headerColor: "#ffffff",
|
|
4271
|
+
endMessage: "See you next time!",
|
|
4272
|
+
endMessageColor: "#ffffff",
|
|
4273
|
+
eventColor: "#ffffff",
|
|
4111
4274
|
loop: false,
|
|
4112
|
-
|
|
4275
|
+
speed: 1,
|
|
4276
|
+
sectionOrder: [...CREDITS_DEFAULT_SECTION_ORDER],
|
|
4277
|
+
// SE only ships subscribers + gift-subs, so import with just those
|
|
4278
|
+
// enabled. The Manager can re-enable additional sections at any time;
|
|
4279
|
+
// the underlying activity feed is fetched session-wide regardless.
|
|
4280
|
+
eventsToShow: { ...SE_CREDITS_EVENTS_TO_SHOW },
|
|
4281
|
+
topLimits: { ...CREDITS_DEFAULT_TOP_LIMITS },
|
|
4282
|
+
eventNames: { ...CREDITS_DEFAULT_EVENT_NAMES },
|
|
4283
|
+
prefixes: { ...CREDITS_DEFAULT_PREFIXES },
|
|
4284
|
+
templates: { ...CREDITS_DEFAULT_TEMPLATES },
|
|
4285
|
+
daysToShow: "session",
|
|
4113
4286
|
itemGap,
|
|
4114
4287
|
reverseFlow,
|
|
4288
|
+
media: {
|
|
4289
|
+
type: "image",
|
|
4290
|
+
content: { src: [], name: [], loop: true, playAudio: true, volume: 1 }
|
|
4291
|
+
},
|
|
4292
|
+
audio: {
|
|
4293
|
+
content: { src: [], name: [], loop: false, volume: 1 }
|
|
4294
|
+
},
|
|
4115
4295
|
// SE-specific knobs preserved as provenance; no direct Lumia equivalent for
|
|
4116
4296
|
// these. `chosenFilter` would narrow eventsToShow if we had a clean mapping;
|
|
4117
4297
|
// `separator` would join entries but Lumia credits uses sectioned cards instead.
|
|
4118
4298
|
se_chosen_filter: v.chosenFilter,
|
|
4119
4299
|
se_separator: v.separator,
|
|
4120
4300
|
se_amount: v.amount
|
|
4301
|
+
},
|
|
4302
|
+
css: {
|
|
4303
|
+
fontSize: 30,
|
|
4304
|
+
lineHeight: 1,
|
|
4305
|
+
fontFamily: "Roboto",
|
|
4306
|
+
fontWeight: "normal",
|
|
4307
|
+
color: "#ffffff",
|
|
4308
|
+
textShadow: "",
|
|
4309
|
+
textAlign: "center",
|
|
4310
|
+
background: "transparent"
|
|
4121
4311
|
}
|
|
4122
4312
|
});
|
|
4123
4313
|
}
|
|
@@ -4560,6 +4750,11 @@ function mapHypetrain(widget) {
|
|
|
4560
4750
|
levelUpSoundUrl: "https://storage.lumiastream.com/overlays/lumia/audio/crowdClap.mp3",
|
|
4561
4751
|
trainEndSoundUrl: "https://storage.lumiastream.com/overlays/lumia/audio/crowdClap.mp3",
|
|
4562
4752
|
audioVolume: 0.5,
|
|
4753
|
+
// Match native defaults so SE-imported trains get the same polished
|
|
4754
|
+
// sprite pack the native module ships with.
|
|
4755
|
+
trainLocoImageUrl: "https://storage.lumiastream.com/overlays/global/hypetrain/train_loco_default.png",
|
|
4756
|
+
rocketImageUrl: "https://storage.lumiastream.com/overlays/global/hypetrain/rocket_default.png",
|
|
4757
|
+
infernoImageUrl: "https://storage.lumiastream.com/overlays/global/hypetrain/inferno_default.png",
|
|
4563
4758
|
// SE config preserved verbatim as provenance — no Lumia equivalent for
|
|
4564
4759
|
// most of these knobs (per-widget animation tunables, sound URLs the
|
|
4565
4760
|
// streamer might want to migrate manually, etc.). Users can inspect
|
package/dist/se-import.js
CHANGED
|
@@ -226,11 +226,11 @@ var LUMIA_DEFAULT_SIZES = {
|
|
|
226
226
|
audio: { width: 200, height: 200 },
|
|
227
227
|
slideshow: { width: 400, height: 220 },
|
|
228
228
|
alert: { width: 700, height: 600 },
|
|
229
|
-
//
|
|
230
|
-
// in" sublabel
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
goal: { width: 740, height:
|
|
229
|
+
// Sized for the SE-style slim layout — title (~24px line) + tight gap +
|
|
230
|
+
// 1.7em bar + optional "Ends in" sublabel collapses to ~70-85 px. 90 gives
|
|
231
|
+
// a small safety margin for larger fonts without leaving dead space in the
|
|
232
|
+
// editor canvas (which doesn't honor the layer's `autoHeight: true`).
|
|
233
|
+
goal: { width: 740, height: 90 },
|
|
234
234
|
timer: { width: 740, height: 80 },
|
|
235
235
|
chatbox: { width: 375, height: 470 },
|
|
236
236
|
eventlist: { width: 375, height: 470 },
|
|
@@ -267,10 +267,20 @@ function translateVariationCondition(seType, seCondition, requirement) {
|
|
|
267
267
|
return { conditionType: "RANDOM", condition: 100 };
|
|
268
268
|
}
|
|
269
269
|
var LUMIA_LAYOUTS = /* @__PURE__ */ new Set(["column", "row", "onlyImage", "onlyText", "imageOver", "textOver"]);
|
|
270
|
+
var SE_LAYOUT_ALIASES = {
|
|
271
|
+
behind: "textOver"
|
|
272
|
+
};
|
|
270
273
|
function translateLayout(seLayout) {
|
|
271
|
-
if (seLayout
|
|
274
|
+
if (!seLayout) return "column";
|
|
275
|
+
const alias = SE_LAYOUT_ALIASES[seLayout];
|
|
276
|
+
if (alias) return alias;
|
|
277
|
+
if (LUMIA_LAYOUTS.has(seLayout)) return seLayout;
|
|
272
278
|
return "column";
|
|
273
279
|
}
|
|
280
|
+
function seLayoutUsesPushText(seLayout) {
|
|
281
|
+
if (!seLayout) return true;
|
|
282
|
+
return seLayout !== "behind";
|
|
283
|
+
}
|
|
274
284
|
|
|
275
285
|
// src/se-import/mappers/build.ts
|
|
276
286
|
import { nanoid } from "nanoid";
|
|
@@ -481,7 +491,7 @@ function buildAlertEvent(seEvent, seEventType) {
|
|
|
481
491
|
const importedTextShadow = css["text-shadow"] ?? "rgba(0, 0, 0, 0.8) 1px 1px 1px";
|
|
482
492
|
const textShadow = shadowEnabled ? importedTextShadow : "none";
|
|
483
493
|
const marginTopRaw = Number(css["margin-top"]);
|
|
484
|
-
const pushTextUp = Number.isFinite(marginTopRaw) ? -marginTopRaw : 0;
|
|
494
|
+
const pushTextUp = seLayoutUsesPushText(seEvent.layout) && Number.isFinite(marginTopRaw) ? -marginTopRaw : 0;
|
|
485
495
|
const variations = (seEvent.variations ?? []).map((variation) => buildAlertVariation(variation, seEventType, seEvent)).filter((v) => v != null);
|
|
486
496
|
const defaultDuration = (seEventType && SE_DEFAULT_DURATION_BY_EVENT[seEventType]) ?? 8;
|
|
487
497
|
return {
|
|
@@ -611,25 +621,52 @@ function deepMergeSeSettings(parent, variation) {
|
|
|
611
621
|
}
|
|
612
622
|
return out;
|
|
613
623
|
}
|
|
624
|
+
function pickBaseAlertFields(event) {
|
|
625
|
+
const { on: _on, variations: _variations, matchEmptyCondition: _mec, ...base } = event;
|
|
626
|
+
return base;
|
|
627
|
+
}
|
|
614
628
|
function mapAlertBox(widget, opts = {}) {
|
|
615
629
|
const v = widget.variables ?? {};
|
|
616
630
|
const events = {};
|
|
617
631
|
const eventKeys = opts.onlyEvents ?? ["follower", "subscriber", "tip", "cheer", "raid", "merch", "purchase", "charityCampaignDonation"];
|
|
632
|
+
let firstEvent = null;
|
|
618
633
|
for (const seKey of eventKeys) {
|
|
619
634
|
const ev = v[seKey];
|
|
620
635
|
if (!ev || typeof ev !== "object") continue;
|
|
621
636
|
const lumiaAlert = SE_EVENT_TO_LUMIA_ALERT[seKey];
|
|
622
637
|
if (!lumiaAlert) continue;
|
|
623
|
-
|
|
638
|
+
const built = buildAlertEvent(ev, seKey);
|
|
639
|
+
events[lumiaAlert] = built;
|
|
640
|
+
if (firstEvent == null) firstEvent = built;
|
|
624
641
|
}
|
|
625
|
-
|
|
642
|
+
const baseAlert = firstEvent ? pickBaseAlertFields(firstEvent) : {};
|
|
643
|
+
return buildUnit(widget, "alert", { alert: { ...baseAlert, events } });
|
|
626
644
|
}
|
|
627
645
|
function mapSingleAlert(widget, lumiaAlertKey) {
|
|
628
646
|
const v = widget.variables ?? {};
|
|
647
|
+
const topText = widget.text;
|
|
648
|
+
const merged = { ...v };
|
|
649
|
+
if (topText) {
|
|
650
|
+
const inner = v.text ?? {};
|
|
651
|
+
const innerCss = inner.css ?? {};
|
|
652
|
+
const topCss = topText.css ?? {};
|
|
653
|
+
merged.text = {
|
|
654
|
+
...inner,
|
|
655
|
+
message: inner.message ?? topText.value ?? "",
|
|
656
|
+
enableShadow: inner.enableShadow ?? topText.enableShadow,
|
|
657
|
+
// Top-level SE CSS is the source of truth for Extra Life / DonorDrive
|
|
658
|
+
// (which omit `variables.text` entirely). For Tiltify both are populated
|
|
659
|
+
// with the same values; letting the nested `variables.text.css` win
|
|
660
|
+
// preserves any per-event overrides the streamer might have set.
|
|
661
|
+
css: { ...topCss, ...innerCss }
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
const built = buildAlertEvent(merged);
|
|
629
665
|
const events = {
|
|
630
|
-
[lumiaAlertKey]:
|
|
666
|
+
[lumiaAlertKey]: built
|
|
631
667
|
};
|
|
632
|
-
|
|
668
|
+
const baseAlert = pickBaseAlertFields(built);
|
|
669
|
+
return buildUnit(widget, "alert", { alert: { ...baseAlert, events } });
|
|
633
670
|
}
|
|
634
671
|
|
|
635
672
|
// src/se-import/mappers/goal.ts
|
|
@@ -645,9 +682,17 @@ function currentForListener(listener) {
|
|
|
645
682
|
if (listener.startsWith("merch-")) return "{{fourthwall_total_order_count}}";
|
|
646
683
|
return "0";
|
|
647
684
|
}
|
|
685
|
+
function charityGoalVariables(widgetType) {
|
|
686
|
+
if (widgetType === "se-widget-tiltify-goal") return { current: "{{tiltify_total_raised=0}}", targetGoal: "{{tiltify_goal_amount=100}}" };
|
|
687
|
+
if (widgetType === "se-widget-extralife-goal") return { current: "{{extralife_total_raised=0}}", targetGoal: "{{extralife_goal_amount=100}}" };
|
|
688
|
+
if (widgetType === "se-widget-donor-drive-goal") return { current: "{{donordrive_total_raised=0}}", targetGoal: "{{donordrive_goal_amount=100}}" };
|
|
689
|
+
return null;
|
|
690
|
+
}
|
|
648
691
|
function mapGoal(widget) {
|
|
649
692
|
const v = widget.variables ?? {};
|
|
650
693
|
const listener = v.goalListener ?? (typeof widget.listener === "string" ? widget.listener : null);
|
|
694
|
+
const charity = charityGoalVariables(widget.type);
|
|
695
|
+
const seTextCss = widget.text?.css ?? {};
|
|
651
696
|
return buildUnit(widget, "goal", {
|
|
652
697
|
content: {
|
|
653
698
|
version: 1,
|
|
@@ -659,11 +704,13 @@ function mapGoal(widget) {
|
|
|
659
704
|
label: translateSeText(v.title ?? "Goal"),
|
|
660
705
|
subLabel: "",
|
|
661
706
|
// The Goal module renders this template literal with {{current}} + {{goal}} substituted.
|
|
662
|
-
|
|
707
|
+
// Charity goals track donation amounts — prefix `$` so the rendered bar reads
|
|
708
|
+
// "$0 / $100" the way SE's charity goals do, instead of bare integers.
|
|
709
|
+
display: charity ? "${{current}} / ${{goal}}" : "{{current}} / {{goal}}",
|
|
663
710
|
// `current` is a template variable reference (resolved at render time from session variables).
|
|
664
711
|
// `targetGoal` is the numeric ceiling. Both required by Goal/index.tsx:28-29.
|
|
665
|
-
current: currentForListener(listener),
|
|
666
|
-
targetGoal: String(v.goalAmount ?? 100),
|
|
712
|
+
current: charity ? charity.current : currentForListener(listener),
|
|
713
|
+
targetGoal: charity ? charity.targetGoal : String(v.goalAmount ?? 100),
|
|
667
714
|
image: "",
|
|
668
715
|
audio: { decrement: "", increment: "", goal: "", goalFailed: "", volume: 1 },
|
|
669
716
|
// `null` (rather than `''`) is the cleaner contract — Goal/index.tsx:11's
|
|
@@ -690,13 +737,13 @@ function mapGoal(widget) {
|
|
|
690
737
|
// `content.border` and `content.borderRadius`. Writing them to
|
|
691
738
|
// module.css just plopped useless transparent-0px rules on the
|
|
692
739
|
// outer .overlay-module wrapper.
|
|
693
|
-
lineHeight: 1,
|
|
694
|
-
fontSize: 30,
|
|
695
|
-
textAlign: "center",
|
|
696
|
-
fontFamily: "Roboto",
|
|
697
|
-
fontWeight: "bold",
|
|
698
|
-
color: "#ffffff",
|
|
699
|
-
textShadow: "rgb(0, 0, 0) 1px 1px 1px",
|
|
740
|
+
lineHeight: seTextCss["line-height"] ?? 1,
|
|
741
|
+
fontSize: seTextCss["font-size"] ?? 30,
|
|
742
|
+
textAlign: seTextCss["text-align"] ?? "center",
|
|
743
|
+
fontFamily: seTextCss["font-family"] ?? "Roboto",
|
|
744
|
+
fontWeight: seTextCss["font-weight"] ?? "bold",
|
|
745
|
+
color: seTextCss.color ?? "#ffffff",
|
|
746
|
+
textShadow: seTextCss["text-shadow"] ?? "rgb(0, 0, 0) 1px 1px 1px",
|
|
700
747
|
background: "transparent"
|
|
701
748
|
}
|
|
702
749
|
});
|
|
@@ -955,33 +1002,143 @@ function mapEventList(widget) {
|
|
|
955
1002
|
}
|
|
956
1003
|
});
|
|
957
1004
|
}
|
|
958
|
-
var
|
|
1005
|
+
var SE_CREDITS_EVENTS_TO_SHOW = {
|
|
959
1006
|
mods: false,
|
|
960
1007
|
subscribers: true,
|
|
961
1008
|
gifts: true,
|
|
962
|
-
donations:
|
|
963
|
-
purchases:
|
|
964
|
-
bits:
|
|
965
|
-
kicks:
|
|
966
|
-
raids:
|
|
967
|
-
hosts:
|
|
968
|
-
superstickers:
|
|
969
|
-
superchats:
|
|
970
|
-
redemptions:
|
|
971
|
-
stars:
|
|
972
|
-
fans:
|
|
1009
|
+
donations: false,
|
|
1010
|
+
purchases: false,
|
|
1011
|
+
bits: false,
|
|
1012
|
+
kicks: false,
|
|
1013
|
+
raids: false,
|
|
1014
|
+
hosts: false,
|
|
1015
|
+
superstickers: false,
|
|
1016
|
+
superchats: false,
|
|
1017
|
+
redemptions: false,
|
|
1018
|
+
stars: false,
|
|
1019
|
+
fans: false,
|
|
973
1020
|
shares: false,
|
|
974
|
-
spells:
|
|
1021
|
+
spells: false,
|
|
975
1022
|
likes: false,
|
|
976
|
-
followers:
|
|
1023
|
+
followers: false,
|
|
977
1024
|
others: false,
|
|
978
|
-
topGifts:
|
|
979
|
-
topBits:
|
|
980
|
-
topKicks:
|
|
981
|
-
topDonations:
|
|
982
|
-
topSuperstickers:
|
|
983
|
-
topSuperchats:
|
|
984
|
-
topRedemptions:
|
|
1025
|
+
topGifts: false,
|
|
1026
|
+
topBits: false,
|
|
1027
|
+
topKicks: false,
|
|
1028
|
+
topDonations: false,
|
|
1029
|
+
topSuperstickers: false,
|
|
1030
|
+
topSuperchats: false,
|
|
1031
|
+
topRedemptions: false
|
|
1032
|
+
};
|
|
1033
|
+
var CREDITS_DEFAULT_SECTION_ORDER = [
|
|
1034
|
+
"topGifts",
|
|
1035
|
+
"topBits",
|
|
1036
|
+
"topKicks",
|
|
1037
|
+
"topDonations",
|
|
1038
|
+
"topSuperstickers",
|
|
1039
|
+
"topSuperchats",
|
|
1040
|
+
"topRedemptions",
|
|
1041
|
+
"subscribers",
|
|
1042
|
+
"gifts",
|
|
1043
|
+
"followers",
|
|
1044
|
+
"donations",
|
|
1045
|
+
"bits",
|
|
1046
|
+
"kicks",
|
|
1047
|
+
"raids",
|
|
1048
|
+
"hosts",
|
|
1049
|
+
"superstickers",
|
|
1050
|
+
"superchats",
|
|
1051
|
+
"redemptions",
|
|
1052
|
+
"others"
|
|
1053
|
+
];
|
|
1054
|
+
var CREDITS_DEFAULT_TOP_LIMITS = {
|
|
1055
|
+
topGifts: 5,
|
|
1056
|
+
topBits: 5,
|
|
1057
|
+
topKicks: 5,
|
|
1058
|
+
topDonations: 5,
|
|
1059
|
+
topSuperstickers: 5,
|
|
1060
|
+
topSuperchats: 5,
|
|
1061
|
+
topRedemptions: 5
|
|
1062
|
+
};
|
|
1063
|
+
var CREDITS_DEFAULT_EVENT_NAMES = {
|
|
1064
|
+
mods: "Mods (Total {{amount}})",
|
|
1065
|
+
topGifts: "Top Gifters",
|
|
1066
|
+
topBits: "Top Cheerers",
|
|
1067
|
+
topKicks: "Top Kicks",
|
|
1068
|
+
topDonations: "Top Donators",
|
|
1069
|
+
topSuperstickers: "Top Super Stickers",
|
|
1070
|
+
topSuperchats: "Top Super Chatters",
|
|
1071
|
+
topRedemptions: "Top Redeemers",
|
|
1072
|
+
subscribers: "Subscribers (Total {{amount}})",
|
|
1073
|
+
gifts: "Gifts (Total {{amount}})",
|
|
1074
|
+
donations: "Donations (Total {{amount}})",
|
|
1075
|
+
purchases: "Purchases (Total {{amount}})",
|
|
1076
|
+
bits: "Cheers (Total {{amount}})",
|
|
1077
|
+
kicks: "Kicks (Total {{amount}})",
|
|
1078
|
+
superstickers: "Super Stickers (Total {{amount}})",
|
|
1079
|
+
superchats: "Super Chatters (Total {{amount}})",
|
|
1080
|
+
redemptions: "Redemptions (Total {{amount}})",
|
|
1081
|
+
stars: "Stars (Total {{amount}})",
|
|
1082
|
+
fans: "Fans (Total {{amount}})",
|
|
1083
|
+
shares: "Shares (Total {{amount}})",
|
|
1084
|
+
raids: "Raids (Total {{amount}})",
|
|
1085
|
+
hosts: "Hosts (Total {{amount}})",
|
|
1086
|
+
spells: "Spells (Total {{amount}})",
|
|
1087
|
+
retweets: "Retweets (Total {{amount}})",
|
|
1088
|
+
likes: "Likes (Total {{amount}})",
|
|
1089
|
+
followers: "Followers (Total {{amount}})",
|
|
1090
|
+
others: "Other (Total {{amount}})"
|
|
1091
|
+
};
|
|
1092
|
+
var CREDITS_DEFAULT_PREFIXES = {
|
|
1093
|
+
mods: "x",
|
|
1094
|
+
subscribers: "x",
|
|
1095
|
+
gifts: "x",
|
|
1096
|
+
donations: "x",
|
|
1097
|
+
purchases: "x",
|
|
1098
|
+
bits: "x",
|
|
1099
|
+
kicks: "x",
|
|
1100
|
+
superstickers: "x",
|
|
1101
|
+
superchats: "x",
|
|
1102
|
+
redemptions: "x",
|
|
1103
|
+
stars: "x",
|
|
1104
|
+
fans: "x",
|
|
1105
|
+
shares: "x",
|
|
1106
|
+
raids: "x",
|
|
1107
|
+
hosts: "x",
|
|
1108
|
+
spells: "x",
|
|
1109
|
+
retweets: "x",
|
|
1110
|
+
likes: "x",
|
|
1111
|
+
followers: "",
|
|
1112
|
+
others: ""
|
|
1113
|
+
};
|
|
1114
|
+
var CREDITS_DEFAULT_TEMPLATES = {
|
|
1115
|
+
mods: "{{username}}",
|
|
1116
|
+
subscribers: "{{username}} x{{amount}}",
|
|
1117
|
+
gifts: "{{username}} x{{amount}}",
|
|
1118
|
+
donations: "{{username}} x{{amount}}",
|
|
1119
|
+
purchases: "{{username}} x{{amount}}",
|
|
1120
|
+
bits: "{{username}} x{{amount}}",
|
|
1121
|
+
kicks: "{{username}} x{{amount}}",
|
|
1122
|
+
raids: "{{username}} x{{amount}}",
|
|
1123
|
+
hosts: "{{username}} x{{amount}}",
|
|
1124
|
+
superstickers: "{{username}} x{{amount}}",
|
|
1125
|
+
superchats: "{{username}} x{{amount}}",
|
|
1126
|
+
redemptions: "{{username}} x{{amount}}",
|
|
1127
|
+
stars: "{{username}} x{{amount}}",
|
|
1128
|
+
fans: "{{username}} x{{amount}}",
|
|
1129
|
+
shares: "{{username}}",
|
|
1130
|
+
spells: "{{username}} x{{amount}}",
|
|
1131
|
+
retweets: "{{username}}",
|
|
1132
|
+
likes: "{{username}}",
|
|
1133
|
+
followers: "{{username}}",
|
|
1134
|
+
others: "{{username}} x{{amount}}",
|
|
1135
|
+
topGifts: "{{username}} x{{amount}}",
|
|
1136
|
+
topBits: "{{username}} x{{amount}}",
|
|
1137
|
+
topKicks: "{{username}} x{{amount}}",
|
|
1138
|
+
topDonations: "{{username}} x{{amount}}",
|
|
1139
|
+
topSuperstickers: "{{username}} x{{amount}}",
|
|
1140
|
+
topSuperchats: "{{username}} x{{amount}}",
|
|
1141
|
+
topRedemptions: "{{username}} x{{amount}}"
|
|
985
1142
|
};
|
|
986
1143
|
function mapCredits(widget) {
|
|
987
1144
|
const v = widget.variables ?? {};
|
|
@@ -989,20 +1146,53 @@ function mapCredits(widget) {
|
|
|
989
1146
|
const reverseFlow = v.direction === "bottom";
|
|
990
1147
|
return buildUnit(widget, "credits", {
|
|
991
1148
|
content: {
|
|
1149
|
+
version: 1,
|
|
992
1150
|
type: "basic",
|
|
993
1151
|
title: "Stream Credits",
|
|
994
|
-
|
|
995
|
-
|
|
1152
|
+
titleColor: "#ffffff",
|
|
1153
|
+
subtitle: "A massive thanks to everyone below",
|
|
1154
|
+
subtitleColor: "#ffffff",
|
|
1155
|
+
headerColor: "#ffffff",
|
|
1156
|
+
endMessage: "See you next time!",
|
|
1157
|
+
endMessageColor: "#ffffff",
|
|
1158
|
+
eventColor: "#ffffff",
|
|
996
1159
|
loop: false,
|
|
997
|
-
|
|
1160
|
+
speed: 1,
|
|
1161
|
+
sectionOrder: [...CREDITS_DEFAULT_SECTION_ORDER],
|
|
1162
|
+
// SE only ships subscribers + gift-subs, so import with just those
|
|
1163
|
+
// enabled. The Manager can re-enable additional sections at any time;
|
|
1164
|
+
// the underlying activity feed is fetched session-wide regardless.
|
|
1165
|
+
eventsToShow: { ...SE_CREDITS_EVENTS_TO_SHOW },
|
|
1166
|
+
topLimits: { ...CREDITS_DEFAULT_TOP_LIMITS },
|
|
1167
|
+
eventNames: { ...CREDITS_DEFAULT_EVENT_NAMES },
|
|
1168
|
+
prefixes: { ...CREDITS_DEFAULT_PREFIXES },
|
|
1169
|
+
templates: { ...CREDITS_DEFAULT_TEMPLATES },
|
|
1170
|
+
daysToShow: "session",
|
|
998
1171
|
itemGap,
|
|
999
1172
|
reverseFlow,
|
|
1173
|
+
media: {
|
|
1174
|
+
type: "image",
|
|
1175
|
+
content: { src: [], name: [], loop: true, playAudio: true, volume: 1 }
|
|
1176
|
+
},
|
|
1177
|
+
audio: {
|
|
1178
|
+
content: { src: [], name: [], loop: false, volume: 1 }
|
|
1179
|
+
},
|
|
1000
1180
|
// SE-specific knobs preserved as provenance; no direct Lumia equivalent for
|
|
1001
1181
|
// these. `chosenFilter` would narrow eventsToShow if we had a clean mapping;
|
|
1002
1182
|
// `separator` would join entries but Lumia credits uses sectioned cards instead.
|
|
1003
1183
|
se_chosen_filter: v.chosenFilter,
|
|
1004
1184
|
se_separator: v.separator,
|
|
1005
1185
|
se_amount: v.amount
|
|
1186
|
+
},
|
|
1187
|
+
css: {
|
|
1188
|
+
fontSize: 30,
|
|
1189
|
+
lineHeight: 1,
|
|
1190
|
+
fontFamily: "Roboto",
|
|
1191
|
+
fontWeight: "normal",
|
|
1192
|
+
color: "#ffffff",
|
|
1193
|
+
textShadow: "",
|
|
1194
|
+
textAlign: "center",
|
|
1195
|
+
background: "transparent"
|
|
1006
1196
|
}
|
|
1007
1197
|
});
|
|
1008
1198
|
}
|
|
@@ -1445,6 +1635,11 @@ function mapHypetrain(widget) {
|
|
|
1445
1635
|
levelUpSoundUrl: "https://storage.lumiastream.com/overlays/lumia/audio/crowdClap.mp3",
|
|
1446
1636
|
trainEndSoundUrl: "https://storage.lumiastream.com/overlays/lumia/audio/crowdClap.mp3",
|
|
1447
1637
|
audioVolume: 0.5,
|
|
1638
|
+
// Match native defaults so SE-imported trains get the same polished
|
|
1639
|
+
// sprite pack the native module ships with.
|
|
1640
|
+
trainLocoImageUrl: "https://storage.lumiastream.com/overlays/global/hypetrain/train_loco_default.png",
|
|
1641
|
+
rocketImageUrl: "https://storage.lumiastream.com/overlays/global/hypetrain/rocket_default.png",
|
|
1642
|
+
infernoImageUrl: "https://storage.lumiastream.com/overlays/global/hypetrain/inferno_default.png",
|
|
1448
1643
|
// SE config preserved verbatim as provenance — no Lumia equivalent for
|
|
1449
1644
|
// most of these knobs (per-widget animation tunables, sound URLs the
|
|
1450
1645
|
// streamer might want to migrate manually, etc.). Users can inspect
|
package/package.json
CHANGED
|
@@ -1,133 +1,133 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
2
|
+
"name": "@lumiastream/ui",
|
|
3
|
+
"version": "0.2.8-alpha.13",
|
|
4
|
+
"author": "Lumia Stream",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"description": "Lumia UI Kit",
|
|
7
|
+
"packageManager": "npm@11.9.0",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"module": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./components": {
|
|
21
|
+
"types": "./dist/components.d.ts",
|
|
22
|
+
"import": "./dist/components.js"
|
|
23
|
+
},
|
|
24
|
+
"./LSButton": {
|
|
25
|
+
"types": "./dist/LSButton.d.ts",
|
|
26
|
+
"import": "./dist/LSButton.js"
|
|
27
|
+
},
|
|
28
|
+
"./LSCheckbox": {
|
|
29
|
+
"types": "./dist/LSCheckbox.d.ts",
|
|
30
|
+
"import": "./dist/LSCheckbox.js"
|
|
31
|
+
},
|
|
32
|
+
"./LSColorPicker": {
|
|
33
|
+
"types": "./dist/LSColorPicker.d.ts",
|
|
34
|
+
"import": "./dist/LSColorPicker.js"
|
|
35
|
+
},
|
|
36
|
+
"./LSDatePicker": {
|
|
37
|
+
"types": "./dist/LSDatePicker.d.ts",
|
|
38
|
+
"import": "./dist/LSDatePicker.js"
|
|
39
|
+
},
|
|
40
|
+
"./LSFontPicker": {
|
|
41
|
+
"types": "./dist/LSFontPicker.d.ts",
|
|
42
|
+
"import": "./dist/LSFontPicker.js"
|
|
43
|
+
},
|
|
44
|
+
"./LSInput": {
|
|
45
|
+
"types": "./dist/LSInput.d.ts",
|
|
46
|
+
"import": "./dist/LSInput.js"
|
|
47
|
+
},
|
|
48
|
+
"./LSMultiSelect": {
|
|
49
|
+
"types": "./dist/LSMultiSelect.d.ts",
|
|
50
|
+
"import": "./dist/LSMultiSelect.js"
|
|
51
|
+
},
|
|
52
|
+
"./LSRadio": {
|
|
53
|
+
"types": "./dist/LSRadio.d.ts",
|
|
54
|
+
"import": "./dist/LSRadio.js"
|
|
55
|
+
},
|
|
56
|
+
"./LSSelect": {
|
|
57
|
+
"types": "./dist/LSSelect.d.ts",
|
|
58
|
+
"import": "./dist/LSSelect.js"
|
|
59
|
+
},
|
|
60
|
+
"./LSSliderInput": {
|
|
61
|
+
"types": "./dist/LSSliderInput.d.ts",
|
|
62
|
+
"import": "./dist/LSSliderInput.js"
|
|
63
|
+
},
|
|
64
|
+
"./LSTextField": {
|
|
65
|
+
"types": "./dist/LSTextField.d.ts",
|
|
66
|
+
"import": "./dist/LSTextField.js"
|
|
67
|
+
},
|
|
68
|
+
"./LSVariableInputField": {
|
|
69
|
+
"types": "./dist/LSVariableInputField.d.ts",
|
|
70
|
+
"import": "./dist/LSVariableInputField.js"
|
|
71
|
+
},
|
|
72
|
+
"./utils": {
|
|
73
|
+
"types": "./dist/utils.d.ts",
|
|
74
|
+
"import": "./dist/utils.js"
|
|
75
|
+
},
|
|
76
|
+
"./utils/chatMedia": {
|
|
77
|
+
"types": "./dist/utils/chatMedia.d.ts",
|
|
78
|
+
"import": "./dist/utils/chatMedia.js"
|
|
79
|
+
},
|
|
80
|
+
"./se-import": {
|
|
81
|
+
"types": "./dist/se-import.d.ts",
|
|
82
|
+
"import": "./dist/se-import.js"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"scripts": {
|
|
86
|
+
"start": "storybook dev -p 6006",
|
|
87
|
+
"build": "tsup",
|
|
88
|
+
"build-storybook": "storybook build",
|
|
89
|
+
"watch": "tsup --watch",
|
|
90
|
+
"release": "changeset && changeset tag && npm run build && npm publish",
|
|
91
|
+
"prepublishOnly": "npm run build",
|
|
92
|
+
"postpublish": "npm cache clean --force && node ./scripts/postpublish-install.mjs"
|
|
93
|
+
},
|
|
94
|
+
"peerDependencies": {
|
|
95
|
+
"@codemirror/autocomplete": "^6.0.0",
|
|
96
|
+
"@emotion/react": "^11.14.0",
|
|
97
|
+
"@emotion/styled": "^11.14.1",
|
|
98
|
+
"@mui/icons-material": "^9.0.0",
|
|
99
|
+
"@mui/material": "^9.0.0",
|
|
100
|
+
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
101
|
+
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
102
|
+
"react-hook-form": "^7.62.0"
|
|
103
|
+
},
|
|
104
|
+
"devDependencies": {
|
|
105
|
+
"@codemirror/autocomplete": "^6.20.1",
|
|
106
|
+
"@emotion/react": "^11.14.0",
|
|
107
|
+
"@emotion/styled": "^11.14.1",
|
|
108
|
+
"@mui/icons-material": "^9.0.0",
|
|
109
|
+
"@mui/material": "^9.0.0",
|
|
110
|
+
"@storybook/builder-vite": "^10.2.17",
|
|
111
|
+
"@storybook/react-vite": "^10.2.17",
|
|
112
|
+
"@types/node": "^25.5.0",
|
|
113
|
+
"@types/react": "^19.2.14",
|
|
114
|
+
"@types/react-dom": "19.2.3",
|
|
115
|
+
"postcss": "^8.5.14",
|
|
116
|
+
"react": "^19.2.0",
|
|
117
|
+
"react-dom": "^19.2.0",
|
|
118
|
+
"react-hook-form": "^7.73.1",
|
|
119
|
+
"sass-embedded": "^1.99.0",
|
|
120
|
+
"storybook": "^10.2.17",
|
|
121
|
+
"tsup": "^8.5.1",
|
|
122
|
+
"typescript": "^5.9.3",
|
|
123
|
+
"vite": "^8.0.8"
|
|
124
|
+
},
|
|
125
|
+
"dependencies": {
|
|
126
|
+
"@lumiastream/lumia-translations": "1.15.7",
|
|
127
|
+
"@lumiastream/lumia-types": "^3.3.7-alpha.2",
|
|
128
|
+
"classnames": "^2.5.1",
|
|
129
|
+
"globals": "^17.4.0",
|
|
130
|
+
"nanoid": "^5.1.11",
|
|
131
|
+
"react-best-gradient-color-picker": "^3.0.14"
|
|
132
|
+
}
|
|
133
133
|
}
|