@lumiastream/ui 0.3.3 → 0.3.5

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 CHANGED
@@ -878,12 +878,12 @@ var LSFontPicker = memo(function LSFontPicker2({
878
878
  transform: "rotate(180deg)"
879
879
  }
880
880
  }
881
- }
882
- },
883
- ListboxProps: {
884
- sx: {
885
- maxHeight: 300,
886
- padding: 0
881
+ },
882
+ listbox: {
883
+ sx: {
884
+ maxHeight: 300,
885
+ padding: 0
886
+ }
887
887
  }
888
888
  },
889
889
  noOptionsText: "No fonts found",
@@ -906,27 +906,39 @@ var LSFontPicker = memo(function LSFontPicker2({
906
906
  key
907
907
  );
908
908
  },
909
- renderInput: (params) => /* @__PURE__ */ jsx8(
910
- TextFieldComponent,
911
- {
912
- ...params,
913
- label,
914
- helperText,
915
- placeholder,
916
- fullWidth: true,
917
- className: "mui-ls-input",
918
- variant: "outlined",
919
- sx: {
920
- "& .MuiOutlinedInput-root": {
921
- paddingRight: "0.5rem"
909
+ renderInput: (params) => {
910
+ const {
911
+ InputLabelProps: paramsInputLabelProps,
912
+ InputProps: paramsInputProps,
913
+ ...restParams
914
+ } = params;
915
+ return /* @__PURE__ */ jsx8(
916
+ TextFieldComponent,
917
+ {
918
+ ...restParams,
919
+ label,
920
+ helperText,
921
+ placeholder,
922
+ fullWidth: true,
923
+ className: "mui-ls-input",
924
+ variant: "outlined",
925
+ sx: {
926
+ "& .MuiOutlinedInput-root": {
927
+ paddingRight: "0.5rem"
928
+ }
929
+ },
930
+ slotProps: {
931
+ inputLabel: {
932
+ shrink: true,
933
+ ...paramsInputLabelProps ?? {}
934
+ },
935
+ input: {
936
+ ...paramsInputProps ?? {}
937
+ }
922
938
  }
923
- },
924
- InputLabelProps: {
925
- shrink: true,
926
- ...params.InputLabelProps ?? {}
927
939
  }
928
- }
929
- )
940
+ );
941
+ }
930
942
  }
931
943
  ) });
932
944
  });
@@ -3123,7 +3135,7 @@ var SE_TO_LUMIA_PLACEHOLDER = {
3123
3135
  displayName: "displayname",
3124
3136
  sender: "gifter",
3125
3137
  amount: "amount",
3126
- currency: "currency",
3138
+ currency: "currencySymbol",
3127
3139
  message: "message",
3128
3140
  items: "itemsDetailed",
3129
3141
  item: "firstItem.name",
@@ -3138,7 +3150,10 @@ var SE_TO_LUMIA_PLACEHOLDER = {
3138
3150
  streamer: "streamer"
3139
3151
  };
3140
3152
  var TWITCH_CONTEXTS = {
3141
- "follower-latest": { name: "twitch_last_follower", username: "twitch_last_follower" },
3153
+ "follower-latest": {
3154
+ name: "twitch_last_follower",
3155
+ username: "twitch_last_follower"
3156
+ },
3142
3157
  // Three SE listeners with genuinely distinct semantics — preserve the
3143
3158
  // distinction in the variable mapping so a widget configured for "Latest
3144
3159
  // new subscriber" doesn't render the latest *resub* (and vice versa).
@@ -3146,9 +3161,18 @@ var TWITCH_CONTEXTS = {
3146
3161
  // are subtype-specific. The dedicated TWITCH_LAST_{NEW_SUBSCRIBER,
3147
3162
  // RESUBSCRIBER} variables are written by the Twitch event pipeline on
3148
3163
  // the matching sub.type event.
3149
- "subscriber-latest": { name: "twitch_last_subscriber", username: "twitch_last_subscriber" },
3150
- "subscriber-new-latest": { name: "twitch_last_new_subscriber", username: "twitch_last_new_subscriber" },
3151
- "subscriber-resub-latest": { name: "twitch_last_resubscriber", username: "twitch_last_resubscriber" },
3164
+ "subscriber-latest": {
3165
+ name: "twitch_last_subscriber",
3166
+ username: "twitch_last_subscriber"
3167
+ },
3168
+ "subscriber-new-latest": {
3169
+ name: "twitch_last_new_subscriber",
3170
+ username: "twitch_last_new_subscriber"
3171
+ },
3172
+ "subscriber-resub-latest": {
3173
+ name: "twitch_last_resubscriber",
3174
+ username: "twitch_last_resubscriber"
3175
+ },
3152
3176
  // `subscriber-gifted-latest`: SE uses `{sender}` for the giver and `{name}` for
3153
3177
  // the recipient (e.g. "{sender} gifted to {name}"). The two roles must point
3154
3178
  // at distinct Lumia variables — collapsing both onto `twitch_last_gifter`
@@ -3156,12 +3180,45 @@ var TWITCH_CONTEXTS = {
3156
3180
  // nowhere. `sender` keeps the gifter; `name` / `username` switch to the
3157
3181
  // dedicated recipient variable `twitch_last_gifted`. Amount stays on the
3158
3182
  // gifter (it's the count of subs in that drop, owned by the gifter).
3159
- "subscriber-gifted-latest": { name: "twitch_last_gifted", username: "twitch_last_gifted", sender: "twitch_last_gifter", amount: "twitch_last_gifter_amount", count: "twitch_last_gifter_amount" },
3160
- "subscriber-alltime-gifter": { name: "twitch_alltime_top_gifter", username: "twitch_alltime_top_gifter", amount: "twitch_alltime_top_gifter_amount", count: "twitch_alltime_top_gifter_amount" },
3161
- "cheer-latest": { name: "twitch_last_bit", username: "twitch_last_bit", amount: "twitch_last_bit_amount", count: "twitch_last_bit_amount" },
3162
- "tip-latest": { name: "latest_donator", username: "latest_donator", amount: "latest_donator_amount", count: "latest_donator_amount", currency: "latest_donator_currency_symbol" },
3163
- latest_donator: { name: "latest_donator", username: "latest_donator", amount: "latest_donator_amount", count: "latest_donator_amount", currency: "latest_donator_currency_symbol" },
3164
- "raid-latest": { name: "twitch_last_raider", username: "twitch_last_raider", amount: "twitch_last_raid_amount", count: "twitch_last_raid_amount" },
3183
+ "subscriber-gifted-latest": {
3184
+ name: "twitch_last_gifted",
3185
+ username: "twitch_last_gifted",
3186
+ sender: "twitch_last_gifter",
3187
+ amount: "twitch_last_gifter_amount",
3188
+ count: "twitch_last_gifter_amount"
3189
+ },
3190
+ "subscriber-alltime-gifter": {
3191
+ name: "twitch_alltime_top_gifter",
3192
+ username: "twitch_alltime_top_gifter",
3193
+ amount: "twitch_alltime_top_gifter_amount",
3194
+ count: "twitch_alltime_top_gifter_amount"
3195
+ },
3196
+ "cheer-latest": {
3197
+ name: "twitch_last_bit",
3198
+ username: "twitch_last_bit",
3199
+ amount: "twitch_last_bit_amount",
3200
+ count: "twitch_last_bit_amount"
3201
+ },
3202
+ "tip-latest": {
3203
+ name: "latest_donator",
3204
+ username: "latest_donator",
3205
+ amount: "latest_donator_amount",
3206
+ count: "latest_donator_amount",
3207
+ currency: "latest_donator_currency_symbol"
3208
+ },
3209
+ latest_donator: {
3210
+ name: "latest_donator",
3211
+ username: "latest_donator",
3212
+ amount: "latest_donator_amount",
3213
+ count: "latest_donator_amount",
3214
+ currency: "latest_donator_currency_symbol"
3215
+ },
3216
+ "raid-latest": {
3217
+ name: "twitch_last_raider",
3218
+ username: "twitch_last_raider",
3219
+ amount: "twitch_last_raid_amount",
3220
+ count: "twitch_last_raid_amount"
3221
+ },
3165
3222
  // Period counters: count/amount = the running counter for that window.
3166
3223
  // SE lets the streamer pick session / week / month / total on the same widget
3167
3224
  // type; the chosen period lands in `widget.listener` (e.g. `cheer-week`).
@@ -3169,25 +3226,86 @@ var TWITCH_CONTEXTS = {
3169
3226
  // table only carried session+total and broke any widget configured for
3170
3227
  // week/month because `{amount}` fell through to the unscoped placeholder
3171
3228
  // and rendered blank.
3172
- "follower-session": { amount: "twitch_session_follower_count", count: "twitch_session_follower_count" },
3173
- "follower-week": { amount: "twitch_week_follower_count", count: "twitch_week_follower_count" },
3174
- "follower-month": { amount: "twitch_month_follower_count", count: "twitch_month_follower_count" },
3175
- "follower-total": { amount: "twitch_total_follower_count", count: "twitch_total_follower_count" },
3176
- "subscriber-session": { amount: "twitch_session_subscribers_count", count: "twitch_session_subscribers_count" },
3177
- "subscriber-week": { amount: "twitch_week_subscriber_count", count: "twitch_week_subscriber_count" },
3178
- "subscriber-month": { amount: "twitch_month_subscriber_count", count: "twitch_month_subscriber_count" },
3179
- "subscriber-total": { amount: "twitch_total_subscriber_count", count: "twitch_total_subscriber_count" },
3180
- "subscriber-new-session": { amount: "twitch_session_new_subscribers_count", count: "twitch_session_new_subscribers_count" },
3181
- "subscriber-resub-session": { amount: "twitch_session_resub_subscribers_count", count: "twitch_session_resub_subscribers_count" },
3182
- "subscriber-gifted-session": { amount: "twitch_session_gifted_subscribers_count", count: "twitch_session_gifted_subscribers_count" },
3183
- "cheer-session": { amount: "twitch_session_bits_count", count: "twitch_session_bits_count" },
3184
- "cheer-week": { amount: "twitch_week_bits_count", count: "twitch_week_bits_count" },
3185
- "cheer-month": { amount: "twitch_month_bits_count", count: "twitch_month_bits_count" },
3186
- "cheer-total": { amount: "twitch_total_bits_count", count: "twitch_total_bits_count" },
3187
- "tip-session": { amount: "session_donation_amount", count: "session_donation_count", currency: "session_donation_amount_currency_symbol" },
3188
- "tip-week": { amount: "week_donation_amount", count: "week_donation_count", currency: "week_donation_amount_currency_symbol" },
3189
- "tip-month": { amount: "month_donation_amount", count: "month_donation_count", currency: "month_donation_amount_currency_symbol" },
3190
- "tip-total": { amount: "total_donation_amount", count: "total_donation_amount", currency: "total_donation_amount_currency_symbol" },
3229
+ "follower-session": {
3230
+ amount: "twitch_session_follower_count",
3231
+ count: "twitch_session_follower_count"
3232
+ },
3233
+ "follower-week": {
3234
+ amount: "twitch_week_follower_count",
3235
+ count: "twitch_week_follower_count"
3236
+ },
3237
+ "follower-month": {
3238
+ amount: "twitch_month_follower_count",
3239
+ count: "twitch_month_follower_count"
3240
+ },
3241
+ "follower-total": {
3242
+ amount: "twitch_total_follower_count",
3243
+ count: "twitch_total_follower_count"
3244
+ },
3245
+ "subscriber-session": {
3246
+ amount: "twitch_session_subscribers_count",
3247
+ count: "twitch_session_subscribers_count"
3248
+ },
3249
+ "subscriber-week": {
3250
+ amount: "twitch_week_subscriber_count",
3251
+ count: "twitch_week_subscriber_count"
3252
+ },
3253
+ "subscriber-month": {
3254
+ amount: "twitch_month_subscriber_count",
3255
+ count: "twitch_month_subscriber_count"
3256
+ },
3257
+ "subscriber-total": {
3258
+ amount: "twitch_total_subscriber_count",
3259
+ count: "twitch_total_subscriber_count"
3260
+ },
3261
+ "subscriber-new-session": {
3262
+ amount: "twitch_session_new_subscribers_count",
3263
+ count: "twitch_session_new_subscribers_count"
3264
+ },
3265
+ "subscriber-resub-session": {
3266
+ amount: "twitch_session_resub_subscribers_count",
3267
+ count: "twitch_session_resub_subscribers_count"
3268
+ },
3269
+ "subscriber-gifted-session": {
3270
+ amount: "twitch_session_gifted_subscribers_count",
3271
+ count: "twitch_session_gifted_subscribers_count"
3272
+ },
3273
+ "cheer-session": {
3274
+ amount: "twitch_session_bits_count",
3275
+ count: "twitch_session_bits_count"
3276
+ },
3277
+ "cheer-week": {
3278
+ amount: "twitch_week_bits_count",
3279
+ count: "twitch_week_bits_count"
3280
+ },
3281
+ "cheer-month": {
3282
+ amount: "twitch_month_bits_count",
3283
+ count: "twitch_month_bits_count"
3284
+ },
3285
+ "cheer-total": {
3286
+ amount: "twitch_total_bits_count",
3287
+ count: "twitch_total_bits_count"
3288
+ },
3289
+ "tip-session": {
3290
+ amount: "session_donation_amount",
3291
+ count: "session_donation_count",
3292
+ currency: "session_donation_amount_currency_symbol"
3293
+ },
3294
+ "tip-week": {
3295
+ amount: "week_donation_amount",
3296
+ count: "week_donation_count",
3297
+ currency: "week_donation_amount_currency_symbol"
3298
+ },
3299
+ "tip-month": {
3300
+ amount: "month_donation_amount",
3301
+ count: "month_donation_count",
3302
+ currency: "month_donation_amount_currency_symbol"
3303
+ },
3304
+ "tip-total": {
3305
+ amount: "total_donation_amount",
3306
+ count: "total_donation_amount",
3307
+ currency: "total_donation_amount_currency_symbol"
3308
+ },
3191
3309
  "tip-count": { amount: "donation_count", count: "donation_count" },
3192
3310
  // Top cheer / cheerer / donator readouts — per period. SE's `se-widget-top-*`
3193
3311
  // widgets encode the chosen period (session / weekly / monthly / alltime) in
@@ -3203,26 +3321,118 @@ var TWITCH_CONTEXTS = {
3203
3321
  // "the user who made the top donation", so the two rows below carry the
3204
3322
  // same name/username mapping — anything else falls through to the unscoped
3205
3323
  // `{{username}}` and renders blank.
3206
- "cheer-session-top-donation": { name: "twitch_session_top_cheerer", username: "twitch_session_top_cheerer", amount: "twitch_session_top_cheer_amount", count: "twitch_session_top_cheer_amount" },
3207
- "cheer-session-top-donator": { name: "twitch_session_top_cheerer", username: "twitch_session_top_cheerer", amount: "twitch_session_top_cheerer_amount", count: "twitch_session_top_cheerer_amount" },
3208
- "cheer-weekly-top-donation": { name: "twitch_week_top_cheerer", username: "twitch_week_top_cheerer", amount: "twitch_week_top_cheerer_amount", count: "twitch_week_top_cheerer_amount" },
3209
- "cheer-weekly-top-donator": { name: "twitch_week_top_cheerer", username: "twitch_week_top_cheerer", amount: "twitch_week_top_cheerer_amount", count: "twitch_week_top_cheerer_amount" },
3210
- "cheer-monthly-top-donation": { name: "twitch_month_top_cheerer", username: "twitch_month_top_cheerer", amount: "twitch_month_top_cheerer_amount", count: "twitch_month_top_cheerer_amount" },
3211
- "cheer-monthly-top-donator": { name: "twitch_month_top_cheerer", username: "twitch_month_top_cheerer", amount: "twitch_month_top_cheerer_amount", count: "twitch_month_top_cheerer_amount" },
3212
- "cheer-alltime-top-donation": { name: "twitch_alltime_top_cheerer", username: "twitch_alltime_top_cheerer", amount: "twitch_alltime_top_cheerer_amount", count: "twitch_alltime_top_cheerer_amount" },
3213
- "cheer-alltime-top-donator": { name: "twitch_alltime_top_cheerer", username: "twitch_alltime_top_cheerer", amount: "twitch_alltime_top_cheerer_amount", count: "twitch_alltime_top_cheerer_amount" },
3214
- "tip-session-top-donation": { name: "session_top_donator", username: "session_top_donator", amount: "session_top_donator_amount", count: "session_top_donator_amount", currency: "session_top_donator_currency_symbol" },
3215
- "tip-session-top-donator": { name: "session_top_donator", username: "session_top_donator", amount: "session_top_donator_amount", count: "session_top_donator_amount", currency: "session_top_donator_currency_symbol" },
3216
- "tip-weekly-top-donation": { name: "week_top_donator", username: "week_top_donator", amount: "week_top_donator_amount", count: "week_top_donator_amount", currency: "week_top_donator_currency_symbol" },
3217
- "tip-weekly-top-donator": { name: "week_top_donator", username: "week_top_donator", amount: "week_top_donator_amount", count: "week_top_donator_amount", currency: "week_top_donator_currency_symbol" },
3218
- "tip-monthly-top-donation": { name: "month_top_donator", username: "month_top_donator", amount: "month_top_donator_amount", count: "month_top_donator_amount", currency: "month_top_donator_currency_symbol" },
3219
- "tip-monthly-top-donator": { name: "month_top_donator", username: "month_top_donator", amount: "month_top_donator_amount", count: "month_top_donator_amount", currency: "month_top_donator_currency_symbol" },
3220
- "tip-alltime-top-donation": { name: "top_donator", username: "top_donator", amount: "top_donator_amount", count: "top_donator_amount", currency: "top_donator_currency_symbol" },
3221
- "tip-alltime-top-donator": { name: "top_donator", username: "top_donator", amount: "top_donator_amount", count: "top_donator_amount", currency: "top_donator_currency_symbol" },
3324
+ "cheer-session-top-donation": {
3325
+ name: "twitch_session_top_cheerer",
3326
+ username: "twitch_session_top_cheerer",
3327
+ amount: "twitch_session_top_cheer_amount",
3328
+ count: "twitch_session_top_cheer_amount"
3329
+ },
3330
+ "cheer-session-top-donator": {
3331
+ name: "twitch_session_top_cheerer",
3332
+ username: "twitch_session_top_cheerer",
3333
+ amount: "twitch_session_top_cheerer_amount",
3334
+ count: "twitch_session_top_cheerer_amount"
3335
+ },
3336
+ "cheer-weekly-top-donation": {
3337
+ name: "twitch_week_top_cheerer",
3338
+ username: "twitch_week_top_cheerer",
3339
+ amount: "twitch_week_top_cheerer_amount",
3340
+ count: "twitch_week_top_cheerer_amount"
3341
+ },
3342
+ "cheer-weekly-top-donator": {
3343
+ name: "twitch_week_top_cheerer",
3344
+ username: "twitch_week_top_cheerer",
3345
+ amount: "twitch_week_top_cheerer_amount",
3346
+ count: "twitch_week_top_cheerer_amount"
3347
+ },
3348
+ "cheer-monthly-top-donation": {
3349
+ name: "twitch_month_top_cheerer",
3350
+ username: "twitch_month_top_cheerer",
3351
+ amount: "twitch_month_top_cheerer_amount",
3352
+ count: "twitch_month_top_cheerer_amount"
3353
+ },
3354
+ "cheer-monthly-top-donator": {
3355
+ name: "twitch_month_top_cheerer",
3356
+ username: "twitch_month_top_cheerer",
3357
+ amount: "twitch_month_top_cheerer_amount",
3358
+ count: "twitch_month_top_cheerer_amount"
3359
+ },
3360
+ "cheer-alltime-top-donation": {
3361
+ name: "twitch_alltime_top_cheerer",
3362
+ username: "twitch_alltime_top_cheerer",
3363
+ amount: "twitch_alltime_top_cheerer_amount",
3364
+ count: "twitch_alltime_top_cheerer_amount"
3365
+ },
3366
+ "cheer-alltime-top-donator": {
3367
+ name: "twitch_alltime_top_cheerer",
3368
+ username: "twitch_alltime_top_cheerer",
3369
+ amount: "twitch_alltime_top_cheerer_amount",
3370
+ count: "twitch_alltime_top_cheerer_amount"
3371
+ },
3372
+ "tip-session-top-donation": {
3373
+ name: "session_top_donator",
3374
+ username: "session_top_donator",
3375
+ amount: "session_top_donator_amount",
3376
+ count: "session_top_donator_amount",
3377
+ currency: "session_top_donator_currency_symbol"
3378
+ },
3379
+ "tip-session-top-donator": {
3380
+ name: "session_top_donator",
3381
+ username: "session_top_donator",
3382
+ amount: "session_top_donator_amount",
3383
+ count: "session_top_donator_amount",
3384
+ currency: "session_top_donator_currency_symbol"
3385
+ },
3386
+ "tip-weekly-top-donation": {
3387
+ name: "week_top_donator",
3388
+ username: "week_top_donator",
3389
+ amount: "week_top_donator_amount",
3390
+ count: "week_top_donator_amount",
3391
+ currency: "week_top_donator_currency_symbol"
3392
+ },
3393
+ "tip-weekly-top-donator": {
3394
+ name: "week_top_donator",
3395
+ username: "week_top_donator",
3396
+ amount: "week_top_donator_amount",
3397
+ count: "week_top_donator_amount",
3398
+ currency: "week_top_donator_currency_symbol"
3399
+ },
3400
+ "tip-monthly-top-donation": {
3401
+ name: "month_top_donator",
3402
+ username: "month_top_donator",
3403
+ amount: "month_top_donator_amount",
3404
+ count: "month_top_donator_amount",
3405
+ currency: "month_top_donator_currency_symbol"
3406
+ },
3407
+ "tip-monthly-top-donator": {
3408
+ name: "month_top_donator",
3409
+ username: "month_top_donator",
3410
+ amount: "month_top_donator_amount",
3411
+ count: "month_top_donator_amount",
3412
+ currency: "month_top_donator_currency_symbol"
3413
+ },
3414
+ "tip-alltime-top-donation": {
3415
+ name: "top_donator",
3416
+ username: "top_donator",
3417
+ amount: "top_donator_amount",
3418
+ count: "top_donator_amount",
3419
+ currency: "top_donator_currency_symbol"
3420
+ },
3421
+ "tip-alltime-top-donator": {
3422
+ name: "top_donator",
3423
+ username: "top_donator",
3424
+ amount: "top_donator_amount",
3425
+ count: "top_donator_amount",
3426
+ currency: "top_donator_currency_symbol"
3427
+ },
3222
3428
  // Botcounter — SE uses `{wins}` for the running chat count; the dispatcher's
3223
3429
  // fallbackVar for `se-widget-botcounter` is `twitch_session_chat_count`, so
3224
3430
  // when the listener arg lands as that var name we treat it as the wins source.
3225
- twitch_session_chat_count: { wins: "twitch_session_chat_count", count: "twitch_session_chat_count", amount: "twitch_session_chat_count" },
3431
+ twitch_session_chat_count: {
3432
+ wins: "twitch_session_chat_count",
3433
+ count: "twitch_session_chat_count",
3434
+ amount: "twitch_session_chat_count"
3435
+ },
3226
3436
  // Merch readouts — SE used to ship via their own shop, now most users route
3227
3437
  // through Fourthwall. Lumia exposes `fourthwall_last_order` as a full object:
3228
3438
  // { username, email, friendlyId, amount, currency, message, items,
@@ -3251,45 +3461,151 @@ var TWITCH_CONTEXTS = {
3251
3461
  }
3252
3462
  };
3253
3463
  var KICK_CONTEXTS = {
3254
- "follower-latest": { name: "kick_last_follower", username: "kick_last_follower" },
3255
- "subscriber-latest": { name: "kick_last_subscriber", username: "kick_last_subscriber" },
3256
- "subscriber-new-latest": { name: "kick_last_subscriber", username: "kick_last_subscriber" },
3257
- "subscriber-resub-latest": { name: "kick_last_subscriber", username: "kick_last_subscriber" },
3464
+ "follower-latest": {
3465
+ name: "kick_last_follower",
3466
+ username: "kick_last_follower"
3467
+ },
3468
+ "subscriber-latest": {
3469
+ name: "kick_last_subscriber",
3470
+ username: "kick_last_subscriber"
3471
+ },
3472
+ "subscriber-new-latest": {
3473
+ name: "kick_last_subscriber",
3474
+ username: "kick_last_subscriber"
3475
+ },
3476
+ "subscriber-resub-latest": {
3477
+ name: "kick_last_subscriber",
3478
+ username: "kick_last_subscriber"
3479
+ },
3258
3480
  // Mirror the Twitch split: `{sender}` = giver, `{name}` = recipient.
3259
3481
  // `kick_last_gifted` was added alongside this mapping; see twitch context
3260
3482
  // above for the rationale (without the split, SE's "{sender} gifted to
3261
3483
  // {name}" renders the gifter on both sides).
3262
- "subscriber-gifted-latest": { name: "kick_last_gifted", username: "kick_last_gifted", sender: "kick_last_gifter", amount: "kick_last_gifter_amount", count: "kick_last_gifter_amount" },
3263
- "cheer-latest": { name: "kick_last_kicks", username: "kick_last_kicks", amount: "kick_last_kicks_amount", count: "kick_last_kicks_amount" },
3264
- "raid-latest": { name: "kick_last_host", username: "kick_last_host", amount: "kick_last_host_amount", count: "kick_last_host_amount" },
3265
- "follower-session": { amount: "kick_session_follower_count", count: "kick_session_follower_count" },
3266
- "subscriber-session": { amount: "kick_session_subscriber_count", count: "kick_session_subscriber_count" },
3267
- "cheer-session": { amount: "kick_session_kicks_count", count: "kick_session_kicks_count" },
3268
- "subscriber-gifted-session": { amount: "kick_session_gifts_count", count: "kick_session_gifts_count" },
3269
- "follower-total": { amount: "kick_total_follower_count", count: "kick_total_follower_count" },
3270
- "subscriber-total": { amount: "kick_total_subscriber_count", count: "kick_total_subscriber_count" },
3271
- "cheer-total": { amount: "kick_total_kicks_count", count: "kick_total_kicks_count" },
3272
- "follower-week": { amount: "kick_week_follower_count", count: "kick_week_follower_count" },
3273
- "follower-month": { amount: "kick_month_follower_count", count: "kick_month_follower_count" },
3274
- "subscriber-week": { amount: "kick_week_subscriber_count", count: "kick_week_subscriber_count" },
3275
- "subscriber-month": { amount: "kick_month_subscriber_count", count: "kick_month_subscriber_count" }
3484
+ "subscriber-gifted-latest": {
3485
+ name: "kick_last_gifted",
3486
+ username: "kick_last_gifted",
3487
+ sender: "kick_last_gifter",
3488
+ amount: "kick_last_gifter_amount",
3489
+ count: "kick_last_gifter_amount"
3490
+ },
3491
+ "cheer-latest": {
3492
+ name: "kick_last_kicks",
3493
+ username: "kick_last_kicks",
3494
+ amount: "kick_last_kicks_amount",
3495
+ count: "kick_last_kicks_amount"
3496
+ },
3497
+ "raid-latest": {
3498
+ name: "kick_last_host",
3499
+ username: "kick_last_host",
3500
+ amount: "kick_last_host_amount",
3501
+ count: "kick_last_host_amount"
3502
+ },
3503
+ "follower-session": {
3504
+ amount: "kick_session_follower_count",
3505
+ count: "kick_session_follower_count"
3506
+ },
3507
+ "subscriber-session": {
3508
+ amount: "kick_session_subscriber_count",
3509
+ count: "kick_session_subscriber_count"
3510
+ },
3511
+ "cheer-session": {
3512
+ amount: "kick_session_kicks_count",
3513
+ count: "kick_session_kicks_count"
3514
+ },
3515
+ "subscriber-gifted-session": {
3516
+ amount: "kick_session_gifts_count",
3517
+ count: "kick_session_gifts_count"
3518
+ },
3519
+ "follower-total": {
3520
+ amount: "kick_total_follower_count",
3521
+ count: "kick_total_follower_count"
3522
+ },
3523
+ "subscriber-total": {
3524
+ amount: "kick_total_subscriber_count",
3525
+ count: "kick_total_subscriber_count"
3526
+ },
3527
+ "cheer-total": {
3528
+ amount: "kick_total_kicks_count",
3529
+ count: "kick_total_kicks_count"
3530
+ },
3531
+ "follower-week": {
3532
+ amount: "kick_week_follower_count",
3533
+ count: "kick_week_follower_count"
3534
+ },
3535
+ "follower-month": {
3536
+ amount: "kick_month_follower_count",
3537
+ count: "kick_month_follower_count"
3538
+ },
3539
+ "subscriber-week": {
3540
+ amount: "kick_week_subscriber_count",
3541
+ count: "kick_week_subscriber_count"
3542
+ },
3543
+ "subscriber-month": {
3544
+ amount: "kick_month_subscriber_count",
3545
+ count: "kick_month_subscriber_count"
3546
+ }
3276
3547
  };
3277
3548
  var YOUTUBE_CONTEXTS = {
3278
- "follower-latest": { name: "youtube_last_subscriber", username: "youtube_last_subscriber" },
3279
- "subscriber-latest": { name: "youtube_last_member", username: "youtube_last_member" },
3280
- "subscriber-new-latest": { name: "youtube_last_member", username: "youtube_last_member" },
3281
- "subscriber-resub-latest": { name: "youtube_last_member", username: "youtube_last_member" },
3282
- "subscriber-gifted-latest": { name: "youtube_last_gift_member", username: "youtube_last_gift_member" },
3283
- "cheer-latest": { name: "youtube_last_superchatter", username: "youtube_last_superchatter" },
3284
- "follower-session": { amount: "youtube_session_subscriber_count", count: "youtube_session_subscriber_count" },
3285
- "subscriber-session": { amount: "youtube_session_member_count", count: "youtube_session_member_count" },
3286
- "cheer-session": { amount: "youtube_session_superchat_count", count: "youtube_session_superchat_count" },
3287
- "follower-total": { amount: "youtube_total_subscriber_count", count: "youtube_total_subscriber_count" },
3288
- "subscriber-total": { amount: "youtube_total_member_count", count: "youtube_total_member_count" },
3289
- "follower-week": { amount: "youtube_week_subscriber_count", count: "youtube_week_subscriber_count" },
3290
- "follower-month": { amount: "youtube_month_subscriber_count", count: "youtube_month_subscriber_count" },
3291
- "subscriber-week": { amount: "youtube_week_member_count", count: "youtube_week_member_count" },
3292
- "subscriber-month": { amount: "youtube_month_member_count", count: "youtube_month_member_count" }
3549
+ "follower-latest": {
3550
+ name: "youtube_last_subscriber",
3551
+ username: "youtube_last_subscriber"
3552
+ },
3553
+ "subscriber-latest": {
3554
+ name: "youtube_last_member",
3555
+ username: "youtube_last_member"
3556
+ },
3557
+ "subscriber-new-latest": {
3558
+ name: "youtube_last_member",
3559
+ username: "youtube_last_member"
3560
+ },
3561
+ "subscriber-resub-latest": {
3562
+ name: "youtube_last_member",
3563
+ username: "youtube_last_member"
3564
+ },
3565
+ "subscriber-gifted-latest": {
3566
+ name: "youtube_last_gift_member",
3567
+ username: "youtube_last_gift_member"
3568
+ },
3569
+ "cheer-latest": {
3570
+ name: "youtube_last_superchatter",
3571
+ username: "youtube_last_superchatter"
3572
+ },
3573
+ "follower-session": {
3574
+ amount: "youtube_session_subscriber_count",
3575
+ count: "youtube_session_subscriber_count"
3576
+ },
3577
+ "subscriber-session": {
3578
+ amount: "youtube_session_member_count",
3579
+ count: "youtube_session_member_count"
3580
+ },
3581
+ "cheer-session": {
3582
+ amount: "youtube_session_superchat_count",
3583
+ count: "youtube_session_superchat_count"
3584
+ },
3585
+ "follower-total": {
3586
+ amount: "youtube_total_subscriber_count",
3587
+ count: "youtube_total_subscriber_count"
3588
+ },
3589
+ "subscriber-total": {
3590
+ amount: "youtube_total_member_count",
3591
+ count: "youtube_total_member_count"
3592
+ },
3593
+ "follower-week": {
3594
+ amount: "youtube_week_subscriber_count",
3595
+ count: "youtube_week_subscriber_count"
3596
+ },
3597
+ "follower-month": {
3598
+ amount: "youtube_month_subscriber_count",
3599
+ count: "youtube_month_subscriber_count"
3600
+ },
3601
+ "subscriber-week": {
3602
+ amount: "youtube_week_member_count",
3603
+ count: "youtube_week_member_count"
3604
+ },
3605
+ "subscriber-month": {
3606
+ amount: "youtube_month_member_count",
3607
+ count: "youtube_month_member_count"
3608
+ }
3293
3609
  };
3294
3610
  var RECENT_TO_LATEST_LISTENER = {
3295
3611
  "follower-recent": "follower-latest",
@@ -3341,11 +3657,14 @@ function translateSeText(input, listener, passthrough, provider, options) {
3341
3657
  if (!input) return "";
3342
3658
  const ctx = listener ? listenerPlaceholderContext(listener, provider) : {};
3343
3659
  const useAlertFallback = (options?.context ?? "alert") === "alert";
3344
- return input.replace(/\{([a-zA-Z][a-zA-Z0-9_.]*)\}/g, (_match, raw) => {
3345
- if (passthrough?.has(raw)) return `{{${raw}}}`;
3346
- const mapped = ctx[raw] ?? (useAlertFallback ? SE_TO_LUMIA_PLACEHOLDER[raw] : void 0) ?? raw;
3347
- return `{{${mapped}}}`;
3348
- });
3660
+ return input.replace(
3661
+ /\{([a-zA-Z][a-zA-Z0-9_.]*)\}/g,
3662
+ (_match, raw) => {
3663
+ if (passthrough?.has(raw)) return `{{${raw}}}`;
3664
+ const mapped = ctx[raw] ?? (useAlertFallback ? SE_TO_LUMIA_PLACEHOLDER[raw] : void 0) ?? raw;
3665
+ return `{{${mapped}}}`;
3666
+ }
3667
+ );
3349
3668
  }
3350
3669
  var KICK_LISTENER_VARS = {
3351
3670
  "follower-latest": "kick_last_follower",
@@ -3388,8 +3707,10 @@ var YOUTUBE_LISTENER_VARS = {
3388
3707
  function listenerToLumiaVariable(listener, provider = "twitch") {
3389
3708
  if (typeof listener !== "string" || !listener) return "username";
3390
3709
  const resolvedListener = RECENT_TO_LATEST_LISTENER[listener] ?? listener;
3391
- if (provider === "kick" && KICK_LISTENER_VARS[resolvedListener]) return KICK_LISTENER_VARS[resolvedListener];
3392
- if (provider === "youtube" && YOUTUBE_LISTENER_VARS[resolvedListener]) return YOUTUBE_LISTENER_VARS[resolvedListener];
3710
+ if (provider === "kick" && KICK_LISTENER_VARS[resolvedListener])
3711
+ return KICK_LISTENER_VARS[resolvedListener];
3712
+ if (provider === "youtube" && YOUTUBE_LISTENER_VARS[resolvedListener])
3713
+ return YOUTUBE_LISTENER_VARS[resolvedListener];
3393
3714
  const m = {
3394
3715
  // Latest events
3395
3716
  "follower-latest": "twitch_last_follower",
@@ -3482,7 +3803,9 @@ function seCssToBounds(css, defaults = { width: 600, height: 200 }, canvas) {
3482
3803
  let x = toPx(css.left, 0, "width");
3483
3804
  let y = toPx(css.top, 0, "height");
3484
3805
  if (typeof css.transform === "string" && css.transform.includes("translate")) {
3485
- const m = /translate\s*\(\s*([^,)]+)\s*(?:,\s*([^)]+))?\s*\)/i.exec(css.transform);
3806
+ const m = /translate\s*\(\s*([^,)]+)\s*(?:,\s*([^)]+))?\s*\)/i.exec(
3807
+ css.transform
3808
+ );
3486
3809
  if (m) {
3487
3810
  const parseShift = (raw, basis) => {
3488
3811
  if (!raw) return 0;
@@ -3552,21 +3875,33 @@ var LUMIA_DEFAULT_SIZES = {
3552
3875
  };
3553
3876
  function translateVariationCondition(seType, seCondition, requirement, seEventType) {
3554
3877
  if (seType === "gift") return { conditionType: "IS_GIFT", condition: 1 };
3555
- if (seType === "communityGift") return { conditionType: "GIFT_SUB_GREATER", condition: requirement ?? 0 };
3878
+ if (seType === "communityGift")
3879
+ return { conditionType: "GIFT_SUB_GREATER", condition: requirement ?? 0 };
3556
3880
  const isSubscriberEvent = seEventType === "subscriber";
3557
3881
  if (isSubscriberEvent && seCondition === "ATLEAST" && requirement != null) {
3558
- return { conditionType: "SUBSCRIBED_MONTHS_GREATER", condition: requirement };
3882
+ return {
3883
+ conditionType: "SUBSCRIBED_MONTHS_GREATER",
3884
+ condition: requirement
3885
+ };
3559
3886
  }
3560
3887
  if (isSubscriberEvent && seCondition === "EXACT" && requirement != null) {
3561
3888
  return { conditionType: "SUBSCRIBED_MONTHS_EQUAL", condition: requirement };
3562
3889
  }
3563
- if (seCondition === "EXACT" && requirement != null) return { conditionType: "EQUAL_NUMBER", condition: requirement };
3890
+ if (seCondition === "EXACT" && requirement != null)
3891
+ return { conditionType: "EQUAL_NUMBER", condition: requirement };
3564
3892
  if (seCondition === "ATLEAST" && requirement != null) {
3565
3893
  return { conditionType: "GREATER_NUMBER", condition: requirement };
3566
3894
  }
3567
3895
  return { conditionType: "RANDOM", condition: 100 };
3568
3896
  }
3569
- var LUMIA_LAYOUTS = /* @__PURE__ */ new Set(["column", "row", "onlyImage", "onlyText", "imageOver", "textOver"]);
3897
+ var LUMIA_LAYOUTS = /* @__PURE__ */ new Set([
3898
+ "column",
3899
+ "row",
3900
+ "onlyImage",
3901
+ "onlyText",
3902
+ "imageOver",
3903
+ "textOver"
3904
+ ]);
3570
3905
  var SE_LAYOUT_ALIASES = {
3571
3906
  behind: "textOver"
3572
3907
  };
@@ -3592,16 +3927,39 @@ function mapSeTextCssToModuleCss(widget, defaults = {}) {
3592
3927
  if (typeof v === "string" && v.length > 0) return v;
3593
3928
  return fallback;
3594
3929
  };
3595
- return {
3596
- lineHeight: asNumOrStr(seTextCss["line-height"], defaults.lineHeight ?? 1),
3930
+ const out = {
3931
+ lineHeight: asNumOrStr(
3932
+ seTextCss["line-height"],
3933
+ defaults.lineHeight ?? "normal"
3934
+ ),
3597
3935
  fontSize: asNumOrStr(seTextCss["font-size"], defaults.fontSize ?? 24),
3598
3936
  textAlign: asStr(seTextCss["text-align"], defaults.textAlign ?? "center"),
3599
- fontFamily: asStr(seTextCss["font-family"], defaults.fontFamily ?? "Roboto"),
3937
+ fontFamily: asStr(
3938
+ seTextCss["font-family"],
3939
+ defaults.fontFamily ?? "Roboto"
3940
+ ),
3600
3941
  fontWeight: asStr(seTextCss["font-weight"], defaults.fontWeight ?? "bold"),
3942
+ fontStyle: asStr(seTextCss["font-style"], defaults.fontStyle ?? "normal"),
3943
+ textTransform: asStr(
3944
+ seTextCss["text-transform"],
3945
+ defaults.textTransform ?? "none"
3946
+ ),
3601
3947
  color: asStr(seTextCss.color, defaults.color ?? "#ffffff"),
3602
- textShadow: asStr(seTextCss["text-shadow"], defaults.textShadow ?? "rgb(0, 0, 0) 1px 1px 1px"),
3948
+ textShadow: asStr(
3949
+ seTextCss["text-shadow"],
3950
+ defaults.textShadow ?? "rgb(0, 0, 0) 1px 1px 1px"
3951
+ ),
3603
3952
  background: defaults.background ?? "transparent"
3604
3953
  };
3954
+ const ls = seTextCss["letter-spacing"];
3955
+ if (typeof ls === "number" || typeof ls === "string" && ls.length > 0) out.letterSpacing = ls;
3956
+ const ws = seTextCss["word-spacing"];
3957
+ if (typeof ws === "number" || typeof ws === "string" && ws.length > 0) out.wordSpacing = ws;
3958
+ const sw = seTextCss["-webkit-text-stroke-width"];
3959
+ if (typeof sw === "number" || typeof sw === "string" && sw.length > 0) out.WebkitTextStrokeWidth = sw;
3960
+ const sc = seTextCss["-webkit-text-stroke-color"];
3961
+ if (typeof sc === "string" && sc.length > 0) out.WebkitTextStrokeColor = sc;
3962
+ return out;
3605
3963
  }
3606
3964
  var READOUT_AUTO_FALLBACK_SIZE = { width: 400, height: 50 };
3607
3965
  function buildUnit(widget, lumiaType, moduleExtras, ctx, sizeOverride) {
@@ -3648,10 +4006,18 @@ function buildUnit(widget, lumiaType, moduleExtras, ctx, sizeOverride) {
3648
4006
  // src/se-import/mappers/basic.ts
3649
4007
  function seExtraTextCss(seCss, scrolling) {
3650
4008
  const extra = {};
3651
- if (typeof seCss["text-decoration"] === "string") extra.textDecoration = seCss["text-decoration"];
3652
- if (typeof seCss["text-transform"] === "string") extra.textTransform = seCss["text-transform"];
3653
- if (seCss["-webkit-text-stroke-color"]) extra["-webkit-text-stroke-color"] = seCss["-webkit-text-stroke-color"];
3654
- if (seCss["-webkit-text-stroke-width"] != null) extra["-webkit-text-stroke-width"] = seCss["-webkit-text-stroke-width"];
4009
+ if (typeof seCss["text-decoration"] === "string")
4010
+ extra.textDecoration = seCss["text-decoration"];
4011
+ if (typeof seCss["text-transform"] === "string")
4012
+ extra.textTransform = seCss["text-transform"];
4013
+ if (typeof seCss["font-style"] === "string")
4014
+ extra.fontStyle = seCss["font-style"];
4015
+ if (seCss["-webkit-text-stroke-color"])
4016
+ extra.WebkitTextStrokeColor = seCss["-webkit-text-stroke-color"];
4017
+ if (seCss["-webkit-text-stroke-width"] != null)
4018
+ extra.WebkitTextStrokeWidth = seCss["-webkit-text-stroke-width"];
4019
+ if (seCss["letter-spacing"] != null) extra.letterSpacing = seCss["letter-spacing"];
4020
+ if (seCss["word-spacing"] != null) extra.wordSpacing = seCss["word-spacing"];
3655
4021
  if (scrolling?.enabled) {
3656
4022
  extra.scroll = true;
3657
4023
  const speed = Number(scrolling.speed);
@@ -3660,54 +4026,82 @@ function seExtraTextCss(seCss, scrolling) {
3660
4026
  return extra;
3661
4027
  }
3662
4028
  function mapText(widget, ctx) {
3663
- const value = translateSeText(widget.text?.value ?? "", null, void 0, ctx?.provider, { context: "static" });
4029
+ const value = translateSeText(
4030
+ widget.text?.value ?? "",
4031
+ null,
4032
+ void 0,
4033
+ ctx?.provider,
4034
+ { context: "static" }
4035
+ );
3664
4036
  const seCss = widget.text?.css ?? {};
3665
- return buildUnit(widget, "text", {
3666
- content: {
3667
- value,
3668
- highlightColor: "inherit"
4037
+ return buildUnit(
4038
+ widget,
4039
+ "text",
4040
+ {
4041
+ content: {
4042
+ value,
4043
+ highlightColor: "inherit"
4044
+ },
4045
+ css: {
4046
+ fontSize: seCss["font-size"] ?? 24,
4047
+ textAlign: seCss["text-align"] ?? "center",
4048
+ fontFamily: seCss["font-family"] ?? "Roboto",
4049
+ fontWeight: seCss["font-weight"] ?? "bold",
4050
+ color: seCss["color"] ?? "#ffffff",
4051
+ textShadow: seCss["text-shadow"] ?? "rgb(0, 0, 0) 1px 1px 1px",
4052
+ lineHeight: seCss["line-height"] ?? "normal",
4053
+ background: "transparent",
4054
+ ...seExtraTextCss(seCss, widget.text?.scrolling)
4055
+ }
3669
4056
  },
3670
- css: {
3671
- fontSize: seCss["font-size"] ?? 24,
3672
- textAlign: seCss["text-align"] ?? "center",
3673
- fontFamily: seCss["font-family"] ?? "Roboto",
3674
- fontWeight: seCss["font-weight"] ?? "bold",
3675
- color: seCss["color"] ?? "#ffffff",
3676
- textShadow: seCss["text-shadow"] ?? "rgb(0, 0, 0) 1px 1px 1px",
3677
- lineHeight: seCss["line-height"] ?? 1,
3678
- background: "transparent",
3679
- ...seExtraTextCss(seCss, widget.text?.scrolling)
3680
- }
3681
- }, ctx);
4057
+ ctx
4058
+ );
3682
4059
  }
3683
4060
  function mapImage(widget, ctx) {
3684
- return buildUnit(widget, "image", {
3685
- content: {
3686
- src: widget.image?.src ?? "",
3687
- loop: true
3688
- }
3689
- }, ctx);
4061
+ return buildUnit(
4062
+ widget,
4063
+ "image",
4064
+ {
4065
+ content: {
4066
+ src: widget.image?.src ?? "",
4067
+ loop: true
4068
+ }
4069
+ },
4070
+ ctx
4071
+ );
3690
4072
  }
3691
4073
  function mapVideo(widget, ctx) {
3692
- return buildUnit(widget, "video", {
3693
- content: {
3694
- src: widget.video?.src ?? "",
3695
- volume: widget.video?.volume ?? 0.5,
3696
- loop: true,
3697
- muted: false
3698
- }
3699
- }, ctx);
4074
+ const unit = buildUnit(
4075
+ widget,
4076
+ "video",
4077
+ {
4078
+ content: {
4079
+ src: widget.video?.src ?? "",
4080
+ volume: widget.video?.volume ?? 0.5,
4081
+ loop: true,
4082
+ muted: false
4083
+ }
4084
+ },
4085
+ ctx
4086
+ );
4087
+ unit.layer.bounds.autoHeight = true;
4088
+ return unit;
3700
4089
  }
3701
4090
  var LUMIA_SNOW_WEBM = "https://storage.lumiastream.com/overlays/global/seasonal/snow.webm";
3702
4091
  function mapSnow(widget, ctx) {
3703
- return buildUnit(widget, "video", {
3704
- content: {
3705
- src: LUMIA_SNOW_WEBM,
3706
- volume: 0,
3707
- loop: true,
3708
- muted: true
3709
- }
3710
- }, ctx);
4092
+ return buildUnit(
4093
+ widget,
4094
+ "video",
4095
+ {
4096
+ content: {
4097
+ src: LUMIA_SNOW_WEBM,
4098
+ volume: 0,
4099
+ loop: true,
4100
+ muted: true
4101
+ }
4102
+ },
4103
+ ctx
4104
+ );
3711
4105
  }
3712
4106
  function mapReadout(widget, fallbackVar, ctx) {
3713
4107
  const explicitListener = widget.variables?.listener;
@@ -3717,7 +4111,9 @@ function mapReadout(widget, fallbackVar, ctx) {
3717
4111
  const variable = listenerToLumiaVariable(listener, ctx?.provider);
3718
4112
  const userTemplate = widget.text?.value ?? "";
3719
4113
  const inheritsText = userTemplate.trim().length > 0 && /\{[a-zA-Z]/.test(userTemplate);
3720
- const value = inheritsText ? translateSeText(userTemplate, listener, void 0, ctx?.provider, { context: "static" }) : `{{${variable}}}`;
4114
+ const value = inheritsText ? translateSeText(userTemplate, listener, void 0, ctx?.provider, {
4115
+ context: "static"
4116
+ }) : `{{${variable}}}`;
3721
4117
  const seCss = widget.text?.css ?? {};
3722
4118
  return buildUnit(
3723
4119
  widget,
@@ -3731,7 +4127,7 @@ function mapReadout(widget, fallbackVar, ctx) {
3731
4127
  fontWeight: seCss["font-weight"] ?? "bold",
3732
4128
  color: seCss["color"] ?? "#ffffff",
3733
4129
  textShadow: seCss["text-shadow"] ?? "rgb(0, 0, 0) 1px 1px 1px",
3734
- lineHeight: seCss["line-height"] ?? 1,
4130
+ lineHeight: seCss["line-height"] ?? "normal",
3735
4131
  background: "transparent",
3736
4132
  ...seExtraTextCss(seCss, widget.text?.scrolling)
3737
4133
  }
@@ -4602,15 +4998,13 @@ function computeAllowedEventsFromSEListeners(seListeners, explicitListener) {
4602
4998
  });
4603
4999
  return allowedAlerts;
4604
5000
  }
4605
- function seScrollSpeedToMarqueeDurationSec(seSpeed) {
4606
- const n = typeof seSpeed === "number" && Number.isFinite(seSpeed) ? seSpeed : 6;
4607
- const clamped = Math.min(20, Math.max(1, n));
4608
- const duration = 60 / clamped;
4609
- return Math.min(120, Math.max(5, Math.round(duration * 10) / 10));
5001
+ var LUMIA_DEFAULT_MARQUEE_PIXELS_PER_SECOND = 20;
5002
+ function seScrollSpeedToPixelsPerSecond(_seSpeed) {
5003
+ return LUMIA_DEFAULT_MARQUEE_PIXELS_PER_SECOND;
4610
5004
  }
4611
5005
  function seTemplateToMarqueeTemplate(seTemplate) {
4612
5006
  if (typeof seTemplate !== "string" || !seTemplate.trim()) return void 0;
4613
- return seTemplate.split("{name}").join("{username}").split("{username}").join("{username}");
5007
+ return translateSeText(seTemplate);
4614
5008
  }
4615
5009
  function mapEventList(widget, ctx) {
4616
5010
  const v = widget.variables ?? {};
@@ -4623,7 +5017,7 @@ function mapEventList(widget, ctx) {
4623
5017
  const scrolling = seText?.scrolling;
4624
5018
  const isMarquee = !!(scrolling && scrolling.enabled === true);
4625
5019
  const itemTemplate = isMarquee ? seTemplateToMarqueeTemplate(seText?.value) : void 0;
4626
- const marqueeSpeed = isMarquee ? seScrollSpeedToMarqueeDurationSec(scrolling?.speed) : void 0;
5020
+ const marqueeSpeed = isMarquee ? seScrollSpeedToPixelsPerSecond(scrolling?.speed) : void 0;
4627
5021
  const marqueeDirection = isMarquee ? scrolling?.direction === "right" ? "right" : "left" : void 0;
4628
5022
  const theme = isMarquee ? "marquee" : v.theme ?? "simple";
4629
5023
  return buildUnit(
@@ -5058,6 +5452,47 @@ function mapTimer(widget, ctx) {
5058
5452
  function mapNowPlaying(widget, ctx) {
5059
5453
  const v = widget.variables ?? {};
5060
5454
  const source = v.provider === "youtube" ? "youtubemusic" : "spotify";
5455
+ const isMarquee = !!v.simpleDesign;
5456
+ const text = widget.text ?? {};
5457
+ const scrolling = text.scrolling ?? {};
5458
+ const seTextCss = text.css ?? {};
5459
+ const seTemplate = typeof text.value === "string" && text.value.trim().length > 0 ? text.value : "";
5460
+ const itemTemplate = seTemplate ? seTemplate.replace(/\{title\}/gi, "{{songTitle}}").replace(/\{artist\}/gi, "{{songArtist}}") : "{{songTitle}} - {{songArtist}}";
5461
+ const marqueeSpeed = 20;
5462
+ const marqueeDirection = scrolling.direction === "right" ? "right" : "left";
5463
+ const wantsShadow = text.enableShadow !== false;
5464
+ const importedCss = {
5465
+ borderRadius: "0px",
5466
+ borderStyle: "solid",
5467
+ borderWidth: "0px",
5468
+ borderColor: "transparent",
5469
+ fontSize: seTextCss["font-size"] ?? 24,
5470
+ textAlign: seTextCss["text-align"] ?? "left",
5471
+ fontFamily: seTextCss["font-family"] ?? "Be Vietnam Pro",
5472
+ fontWeight: seTextCss["font-weight"] ?? "bold",
5473
+ color: seTextCss["color"] ?? "#ffffff",
5474
+ textShadow: wantsShadow ? seTextCss["text-shadow"] ?? "rgb(0, 0, 0) 1px 1px 1px" : "none",
5475
+ // `normal` (not `1`) when SE didn't specify — see the same fix in
5476
+ // `build.ts::mapSeTextCssToModuleCss` and `basic.ts::mapText` for the
5477
+ // rationale. This path is the now-playing / current-song mapper, which
5478
+ // is the one the user noticed had a too-tight line-height in the
5479
+ // marquee render.
5480
+ lineHeight: seTextCss["line-height"] ?? "normal",
5481
+ background: "transparent"
5482
+ };
5483
+ if (typeof seTextCss["text-transform"] === "string")
5484
+ importedCss.textTransform = seTextCss["text-transform"];
5485
+ if (typeof seTextCss["font-style"] === "string")
5486
+ importedCss.fontStyle = seTextCss["font-style"];
5487
+ if (typeof seTextCss["text-decoration"] === "string")
5488
+ importedCss.textDecoration = seTextCss["text-decoration"];
5489
+ if (typeof seTextCss["letter-spacing"] === "string" || typeof seTextCss["letter-spacing"] === "number") {
5490
+ importedCss.letterSpacing = seTextCss["letter-spacing"];
5491
+ }
5492
+ if (seTextCss["-webkit-text-stroke-color"])
5493
+ importedCss["-webkit-text-stroke-color"] = seTextCss["-webkit-text-stroke-color"];
5494
+ if (seTextCss["-webkit-text-stroke-width"] != null)
5495
+ importedCss["-webkit-text-stroke-width"] = seTextCss["-webkit-text-stroke-width"];
5061
5496
  return buildUnit(
5062
5497
  widget,
5063
5498
  "nowplaying",
@@ -5066,7 +5501,7 @@ function mapNowPlaying(widget, ctx) {
5066
5501
  version: 1,
5067
5502
  type: "nowplaying",
5068
5503
  source,
5069
- theme: "basic",
5504
+ theme: isMarquee ? "marquee" : "basic",
5070
5505
  borderRadius: "30px",
5071
5506
  songTitle: `{{${source}_now_playing_song=Lumia Dream}}`,
5072
5507
  songArtist: `{{${source}_now_playing_artist}}`,
@@ -5074,20 +5509,14 @@ function mapNowPlaying(widget, ctx) {
5074
5509
  showImg: true,
5075
5510
  oneLineTitle: false,
5076
5511
  highlightColor: "inherit",
5512
+ ...isMarquee ? {
5513
+ marqueeSpeed,
5514
+ marqueeDirection,
5515
+ themeConfig: { itemTemplate }
5516
+ } : {},
5077
5517
  importMeta: buildImportMeta(widget, { simpleDesign: !!v.simpleDesign })
5078
5518
  },
5079
- css: {
5080
- borderRadius: "0px",
5081
- borderStyle: "solid",
5082
- borderWidth: "0px",
5083
- borderColor: "transparent",
5084
- lineHeight: 1,
5085
- textAlign: "left",
5086
- fontFamily: "Be Vietnam Pro",
5087
- color: "#ffffff",
5088
- textShadow: "rgb(0, 0, 0) 1px 1px 1px",
5089
- background: "transparent"
5090
- }
5519
+ css: importedCss
5091
5520
  },
5092
5521
  ctx
5093
5522
  );
@@ -5506,6 +5935,22 @@ function mapEmoteWall(widget, ctx) {
5506
5935
  );
5507
5936
  }
5508
5937
  function mapUnsupportedAsText(widget, ctx) {
5938
+ const userTemplate = typeof widget.text?.value === "string" ? widget.text.value.trim() : "";
5939
+ const inheritsText = userTemplate.length > 0 && /\{[a-zA-Z]/.test(userTemplate);
5940
+ if (inheritsText) {
5941
+ return buildUnit(
5942
+ widget,
5943
+ "text",
5944
+ {
5945
+ css: mapSeTextCssToModuleCss(widget, { fontSize: 24 }),
5946
+ content: {
5947
+ value: translateSeText(userTemplate),
5948
+ highlightColor: "inherit"
5949
+ }
5950
+ },
5951
+ ctx
5952
+ );
5953
+ }
5509
5954
  return buildUnit(
5510
5955
  widget,
5511
5956
  "text",