hudini 0.18.0 → 0.19.0

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.
Files changed (36) hide show
  1. package/README.md +57 -0
  2. package/dist/components/card/card.d.ts.map +1 -1
  3. package/dist/components/card/card.js +2 -1
  4. package/dist/components/card/card.js.map +1 -1
  5. package/dist/components/flat-icon-button/flat-icon-button.js +3 -3
  6. package/dist/components/flat-section-header/flat-section-header.js +1 -1
  7. package/dist/components/flat-text-button/flat-text-button.d.ts.map +1 -1
  8. package/dist/components/flat-text-button/flat-text-button.js +3 -3
  9. package/dist/components/flat-text-button/flat-text-button.js.map +1 -1
  10. package/dist/components/icon-button/icon-button.d.ts.map +1 -1
  11. package/dist/components/icon-button/icon-button.js +3 -2
  12. package/dist/components/icon-button/icon-button.js.map +1 -1
  13. package/dist/components/text-button/text-button.d.ts.map +1 -1
  14. package/dist/components/text-button/text-button.js +3 -3
  15. package/dist/components/text-button/text-button.js.map +1 -1
  16. package/dist/components/text-button/text-button.spec.js +10 -1
  17. package/dist/components/text-button/text-button.spec.js.map +1 -1
  18. package/dist/hudini.js +270 -42
  19. package/dist/hudini.min.js +1 -1
  20. package/dist/scene/index.d.ts +1 -0
  21. package/dist/scene/index.d.ts.map +1 -1
  22. package/dist/scene/index.js +1 -0
  23. package/dist/scene/index.js.map +1 -1
  24. package/dist/scene/scene-with-hudini.d.ts +24 -1
  25. package/dist/scene/scene-with-hudini.d.ts.map +1 -1
  26. package/dist/scene/scene-with-hudini.js +24 -1
  27. package/dist/scene/scene-with-hudini.js.map +1 -1
  28. package/dist/scene/with-hudini.d.ts +35 -0
  29. package/dist/scene/with-hudini.d.ts.map +1 -0
  30. package/dist/scene/with-hudini.js +33 -0
  31. package/dist/scene/with-hudini.js.map +1 -0
  32. package/dist/utils/color-variants.d.ts +6 -1
  33. package/dist/utils/color-variants.d.ts.map +1 -1
  34. package/dist/utils/color-variants.js +18 -5
  35. package/dist/utils/color-variants.js.map +1 -1
  36. package/package.json +2 -2
package/dist/hudini.js CHANGED
@@ -933,6 +933,19 @@
933
933
  }
934
934
  return null;
935
935
  };
936
+ /**
937
+ * Normalizes a color by adding -500 if only color name is provided
938
+ * @param color - Color token or color name
939
+ * @returns Normalized color token
940
+ */
941
+ const normalizeColorToken = (color) => {
942
+ if (typeof color === 'string' && !String(color).includes('-')) {
943
+ if (color in palette && color !== 'black' && color !== 'white') {
944
+ return `${color}-500`;
945
+ }
946
+ }
947
+ return color;
948
+ };
936
949
  /**
937
950
  * Get RGB string representation of a color
938
951
  * @param color - Color token, theme color key or valid color string
@@ -949,25 +962,27 @@
949
962
  if (colorFromTheme) {
950
963
  return rgb(colorFromTheme);
951
964
  }
952
- const parts = color?.split('-') ?? [];
965
+ // Normalize color: add -500 if only color name is provided
966
+ const normalizedColor = normalizeColorToken(color);
967
+ const parts = normalizedColor?.split('-') ?? [];
953
968
  if (parts.length === 2) {
954
969
  const colorKey = parts[0];
955
970
  const shade = parts[1];
956
971
  const colorValue = palette[colorKey]?.[shade];
957
972
  if (!colorValue) {
958
- if (isValidColor(color)) {
959
- return color;
973
+ if (isValidColor(normalizedColor)) {
974
+ return normalizedColor;
960
975
  }
961
976
  throw new Error(`Color token "${colorKey}-${shade}" not found`);
962
977
  }
963
978
  return colorValue;
964
979
  }
965
- const colorValue = palette[color];
980
+ const colorValue = palette[normalizedColor];
966
981
  if (!colorValue) {
967
- if (isValidColor(color)) {
968
- return color;
982
+ if (isValidColor(normalizedColor)) {
983
+ return normalizedColor;
969
984
  }
970
- throw new Error(`Color token "${color}" not found`);
985
+ throw new Error(`Color token "${normalizedColor}" not found`);
971
986
  }
972
987
  return colorValue;
973
988
  };
@@ -998,24 +1013,26 @@
998
1013
  if (colorFromTheme) {
999
1014
  return hex(colorFromTheme);
1000
1015
  }
1001
- const parts = color?.split('-') ?? [];
1016
+ // Normalize color: add -500 if only color name is provided
1017
+ const normalizedColor = normalizeColorToken(color);
1018
+ const parts = normalizedColor?.split('-') ?? [];
1002
1019
  if (parts.length === 2) {
1003
1020
  const colorKey = parts[0];
1004
1021
  const shade = parts[1];
1005
1022
  const colorValue = palette[colorKey]?.[shade];
1006
1023
  if (!colorValue) {
1007
- if (isValidColor(color)) {
1008
- return convertColorValueToNumber(color);
1024
+ if (isValidColor(normalizedColor)) {
1025
+ return convertColorValueToNumber(normalizedColor);
1009
1026
  }
1010
1027
  throw new Error(`Color token "${colorKey}-${shade}" not found`);
1011
1028
  }
1012
1029
  return convertColorValueToNumber(colorValue);
1013
1030
  }
1014
- const colorToConvert = palette[color];
1031
+ const colorToConvert = palette[normalizedColor];
1015
1032
  if (isValidColor(colorToConvert)) {
1016
1033
  return convertColorValueToNumber(colorToConvert);
1017
1034
  }
1018
- throw new Error(`Color token "${color}" not found`);
1035
+ throw new Error(`Color token "${normalizedColor}" not found`);
1019
1036
  };
1020
1037
  const api = {
1021
1038
  rgb,
@@ -1181,6 +1198,65 @@
1181
1198
  };
1182
1199
  };
1183
1200
 
1201
+ /**
1202
+ * Opacity scale mapping following Tailwind's opacity scale.
1203
+ * Values are in the 0..1 range, ready for Phaser's `setAlpha()`.
1204
+ */
1205
+ const opacityMap = {
1206
+ '0': 0,
1207
+ '5': 0.05,
1208
+ '10': 0.1,
1209
+ '15': 0.15,
1210
+ '20': 0.2,
1211
+ '25': 0.25,
1212
+ '30': 0.3,
1213
+ '35': 0.35,
1214
+ '40': 0.4,
1215
+ '45': 0.45,
1216
+ '50': 0.5,
1217
+ '55': 0.55,
1218
+ '60': 0.6,
1219
+ '65': 0.65,
1220
+ '70': 0.7,
1221
+ '75': 0.75,
1222
+ '80': 0.8,
1223
+ '85': 0.85,
1224
+ '90': 0.9,
1225
+ '95': 0.95,
1226
+ '100': 1,
1227
+ };
1228
+ /**
1229
+ * Create an opacity API bound to an optional theme opacity map.
1230
+ * @example
1231
+ * const o = createOpacity({ faded: 0.35 });
1232
+ * o.value('faded'); // 0.35
1233
+ * o.value('50'); // 0.5
1234
+ */
1235
+ const createOpacity = (themeOpacity) => {
1236
+ const map = {
1237
+ ...opacityMap,
1238
+ ...themeOpacity,
1239
+ };
1240
+ const get = (key) => {
1241
+ return typeof map[key] === 'number' ? map[key] : 0;
1242
+ };
1243
+ return {
1244
+ value: (key) => {
1245
+ return get(key);
1246
+ },
1247
+ percent: (key) => {
1248
+ const ONE_HUNDRED = 100;
1249
+ return get(key) * ONE_HUNDRED;
1250
+ },
1251
+ css: (key) => {
1252
+ const ONE_HUNDRED = 100;
1253
+ return `${get(key) * ONE_HUNDRED}%`;
1254
+ },
1255
+ };
1256
+ };
1257
+ /** Convenience instance using default opacity map (no theme). */
1258
+ const Opacity = createOpacity(undefined);
1259
+
1184
1260
  /**
1185
1261
  * Mapping of radius keys to their pixel values
1186
1262
  */
@@ -1353,6 +1429,7 @@
1353
1429
  overlay: 'black',
1354
1430
  },
1355
1431
  spacing: { ...spacingMap },
1432
+ opacity: { ...opacityMap },
1356
1433
  typography: {
1357
1434
  heading: {
1358
1435
  fontSize: '2xl',
@@ -1429,6 +1506,7 @@
1429
1506
  overlay: 'black',
1430
1507
  },
1431
1508
  spacing: { ...spacingMap },
1509
+ opacity: { ...opacityMap },
1432
1510
  typography: {
1433
1511
  heading: {
1434
1512
  fontSize: '2xl',
@@ -1490,6 +1568,7 @@
1490
1568
  fontSizeInstance = null;
1491
1569
  spacingInstance = null;
1492
1570
  radiusInstance = null;
1571
+ opacityInstance = null;
1493
1572
  fontInstance = null;
1494
1573
  shadowInstance = null;
1495
1574
  /** Current theme configuration */
@@ -1536,6 +1615,7 @@
1536
1615
  this.fontSizeInstance = createFontSize(this.theme.fontSizes);
1537
1616
  this.spacingInstance = createSpacing(this.theme.spacing);
1538
1617
  this.radiusInstance = createRadius(this.theme.radius);
1618
+ this.opacityInstance = createOpacity(this.theme.opacity);
1539
1619
  this.fontInstance = createFont(this.theme.fonts, this.theme.fontSizes);
1540
1620
  this.shadowInstance = createShadow(this.theme.effects);
1541
1621
  }
@@ -1558,6 +1638,9 @@
1558
1638
  get radius() {
1559
1639
  return this.radiusInstance;
1560
1640
  }
1641
+ get opacity() {
1642
+ return this.opacityInstance;
1643
+ }
1561
1644
  get font() {
1562
1645
  return this.fontInstance;
1563
1646
  }
@@ -1566,9 +1649,31 @@
1566
1649
  }
1567
1650
  }
1568
1651
 
1652
+ /**
1653
+ * @deprecated Use {@link withPhaserWind} instead.
1654
+ *
1655
+ * Forces single inheritance, which conflicts with any user-defined `BaseScene`
1656
+ * or other libraries that ship their own scene base class. It also relies on a
1657
+ * non-null assertion (`pw!`) that lies to TypeScript about when the plugin is
1658
+ * available — touching `this.pw` before the plugin mounts throws at runtime.
1659
+ *
1660
+ * Prefer the `withPhaserWind(scene)` accessor:
1661
+ *
1662
+ * ```ts
1663
+ * import { withPhaserWind } from 'phaser-wind';
1664
+ * import type { ThemeType } from './theme';
1665
+ *
1666
+ * class MyScene extends Phaser.Scene {
1667
+ * create() {
1668
+ * const pw = withPhaserWind<ThemeType>(this);
1669
+ * }
1670
+ * }
1671
+ * ```
1672
+ *
1673
+ * Kept exported to avoid breaking existing consumers.
1674
+ */
1569
1675
  class SceneWithPhaserWind extends Phaser.Scene {
1570
1676
  /**
1571
- *
1572
1677
  * @param config The scene key or scene specific configuration settings.
1573
1678
  */
1574
1679
  constructor(config) {
@@ -1577,6 +1682,37 @@
1577
1682
  pw;
1578
1683
  }
1579
1684
 
1685
+ /**
1686
+ * Accessor for the Phaser Wind plugin from within a Phaser scene.
1687
+ *
1688
+ * Preferred over {@link SceneWithPhaserWind} (inheritance) and over module
1689
+ * augmentation of `Phaser.Scene`, because it:
1690
+ * - Composes with any existing base scene (no forced inheritance).
1691
+ * - Keeps the theme type explicit at the call site (no silent `any`).
1692
+ * - Doesn't rely on non-null assertions that lie about lifecycle.
1693
+ *
1694
+ * Call it inside `create()` / `update()` (after the plugin has been installed).
1695
+ *
1696
+ * @typeParam T - The theme config type. Pass your `ThemeType` to get
1697
+ * type-narrowed access to your custom tokens.
1698
+ * @param scene - The Phaser scene instance.
1699
+ * @returns The Phaser Wind plugin instance bound to the given theme type.
1700
+ *
1701
+ * @example
1702
+ * ```ts
1703
+ * import { withPhaserWind } from 'phaser-wind';
1704
+ * import type { ThemeType } from './theme';
1705
+ *
1706
+ * class MyScene extends Phaser.Scene {
1707
+ * create() {
1708
+ * const pw = withPhaserWind<ThemeType>(this);
1709
+ * this.cameras.main.setBackgroundColor(pw.color.rgb('background'));
1710
+ * }
1711
+ * }
1712
+ * ```
1713
+ */
1714
+ const withPhaserWind = (scene) => scene.plugins.get(PHASER_WIND_KEY);
1715
+
1580
1716
  var getPWFromScene$1 = function (scene) {
1581
1717
  return scene.pw;
1582
1718
  };
@@ -1685,7 +1821,8 @@
1685
1821
  // Border constants
1686
1822
  var BLACK_BORDER_THICKNESS$b = 2;
1687
1823
  var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$b = 2;
1688
- var WHITE_BORDER_TOTAL_EXTRA_PIXELS$b = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$b * 2; // 4 pixels total
1824
+ // eslint-disable-next-line no-magic-numbers
1825
+ var WHITE_BORDER_TOTAL_EXTRA_PIXELS$b = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$b * 3; // 6 pixels total
1689
1826
  var WHITE_BORDER_RADIUS_EXTRA$b = 2;
1690
1827
  /**
1691
1828
  * A flexible card component that adapts to its child content size
@@ -4220,8 +4357,8 @@
4220
4357
  var POINTER_DOWN_SCALE$5 = 0.95;
4221
4358
  // Border constants
4222
4359
  var BLACK_BORDER_THICKNESS$a = 2;
4223
- var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$a = 2;
4224
- var WHITE_BORDER_TOTAL_EXTRA_PIXELS$a = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$a * 2; // 4 pixels total
4360
+ var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$a = 3;
4361
+ var WHITE_BORDER_TOTAL_EXTRA_PIXELS$a = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$a * 2; // 6 pixels total
4225
4362
  var WHITE_BORDER_RADIUS_EXTRA$a = 2;
4226
4363
  // Icon constants
4227
4364
  var ICON_STROKE_THICKNESS$3 = 3;
@@ -4234,7 +4371,7 @@
4234
4371
  var FlatIconButton$1 = /** @class */ (function (_super) {
4235
4372
  __extends(FlatIconButton, _super);
4236
4373
  function FlatIconButton(_a) {
4237
- var scene = _a.scene, x = _a.x, y = _a.y, icon = _a.icon, _b = _a.iconStyle, iconStyle = _b === void 0 ? 'solid' : _b, size = _a.size, _c = _a.backgroundColor, backgroundColor = _c === void 0 ? 'gray-600' : _c, _d = _a.iconColor, iconColor = _d === void 0 ? 'white' : _d, onClick = _a.onClick, _e = _a.borderRadius, borderRadius = _e === void 0 ? 'md' : _e, _f = _a.backgroundOpacity, backgroundOpacity = _f === void 0 ? 1 : _f, _g = _a.iconOpacity, iconOpacity = _g === void 0 ? 1 : _g;
4374
+ var scene = _a.scene, x = _a.x, y = _a.y, icon = _a.icon, _b = _a.iconStyle, iconStyle = _b === void 0 ? 'solid' : _b, size = _a.size, _c = _a.backgroundColor, backgroundColor = _c === void 0 ? 'blue-500' : _c, _d = _a.iconColor, iconColor = _d === void 0 ? 'white' : _d, onClick = _a.onClick, _e = _a.borderRadius, borderRadius = _e === void 0 ? 'md' : _e, _f = _a.backgroundOpacity, backgroundOpacity = _f === void 0 ? 1 : _f, _g = _a.iconOpacity, iconOpacity = _g === void 0 ? 1 : _g;
4238
4375
  var _this = _super.call(this, scene, x, y) || this;
4239
4376
  _this.backgroundOpacityValue = 1;
4240
4377
  _this.iconOpacityValue = 1;
@@ -4590,7 +4727,8 @@
4590
4727
  // Border constants
4591
4728
  const BLACK_BORDER_THICKNESS$9 = 2;
4592
4729
  const WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$9 = 2;
4593
- const WHITE_BORDER_TOTAL_EXTRA_PIXELS$9 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$9 * 2; // 4 pixels total
4730
+ // eslint-disable-next-line no-magic-numbers
4731
+ const WHITE_BORDER_TOTAL_EXTRA_PIXELS$9 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$9 * 3; // 6 pixels total
4594
4732
  const WHITE_BORDER_RADIUS_EXTRA$9 = 2;
4595
4733
  /**
4596
4734
  * A flexible card component that adapts to its child content size
@@ -5085,8 +5223,8 @@
5085
5223
  const POINTER_DOWN_SCALE$4 = 0.95;
5086
5224
  // Border constants
5087
5225
  const BLACK_BORDER_THICKNESS$8 = 2;
5088
- const WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$8 = 2;
5089
- const WHITE_BORDER_TOTAL_EXTRA_PIXELS$8 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$8 * 2; // 4 pixels total
5226
+ const WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$8 = 3;
5227
+ const WHITE_BORDER_TOTAL_EXTRA_PIXELS$8 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$8 * 2; // 6 pixels total
5090
5228
  const WHITE_BORDER_RADIUS_EXTRA$8 = 2;
5091
5229
  // Icon constants
5092
5230
  const ICON_STROKE_THICKNESS$2 = 3;
@@ -5107,7 +5245,7 @@
5107
5245
  iconColorValue; // rgb string
5108
5246
  backgroundOpacityValue = 1;
5109
5247
  iconOpacityValue = 1;
5110
- constructor({ scene, x, y, icon, iconStyle = 'solid', size, backgroundColor = 'gray-600', iconColor = 'white', onClick, borderRadius = 'md', backgroundOpacity = 1, iconOpacity = 1, }) {
5248
+ constructor({ scene, x, y, icon, iconStyle = 'solid', size, backgroundColor = 'blue-500', iconColor = 'white', onClick, borderRadius = 'md', backgroundOpacity = 1, iconOpacity = 1, }) {
5111
5249
  super(scene, x, y);
5112
5250
  this.pw = getPWFromScene(scene);
5113
5251
  this.baseSizePx =
@@ -5386,7 +5524,7 @@
5386
5524
  /**
5387
5525
  * Calculates a color variant by adjusting brightness.
5388
5526
  *
5389
- * @param color - The base color (can be a Phaser Wind token like "blue-500" or a CSS color like "#3B82F6")
5527
+ * @param color - The base color (can be a Phaser Wind token like "blue-500", a color name like "red", or a CSS color like "#3B82F6")
5390
5528
  * @param tokenDiff - Amount to adjust the shade for color tokens. Positive values make it darker, negative lighter.
5391
5529
  * For example: -400 for lighter (blue-500 → blue-100), +400 for darker (blue-500 → blue-900)
5392
5530
  * @param colorDiff - Amount to lighten/darken CSS colors. Positive values lighten, negative values darken.
@@ -5394,6 +5532,7 @@
5394
5532
  * @returns The adjusted color as a number
5395
5533
  *
5396
5534
  * @remarks
5535
+ * - If only a color name is provided without a shade (e.g., "red"), it automatically adds "-500" as the default shade
5397
5536
  * - If a color token is provided (e.g., "blue-500"), it uses the token system to calculate variants
5398
5537
  * by adjusting the shade value with tokenDiff (clamped between 100-900)
5399
5538
  * - If a CSS color is provided (hex or rgb), it uses Phaser's lighten/darken methods
@@ -5401,6 +5540,10 @@
5401
5540
  *
5402
5541
  * @example
5403
5542
  * ```typescript
5543
+ * // Using color name only - defaults to -500
5544
+ * const defaultRed = getColorVariant('red', 0, 0);
5545
+ * // Returns red-500 color value
5546
+ *
5404
5547
  * // Using color token - lighter variant
5405
5548
  * const lightBlue = getColorVariant('blue-500', -400, 0);
5406
5549
  * // Returns blue-100 color value
@@ -5419,10 +5562,18 @@
5419
5562
  * ```
5420
5563
  */
5421
5564
  const getColorVariant$1 = (color, tokenDiff, colorDiff) => {
5422
- const colorRgb = Color.rgb(color);
5423
- if (Color.isValidColorToken(color)) {
5565
+ // If only the color name is provided (without shade), validate and add -500 as default
5566
+ let normalizedColor = color;
5567
+ if (typeof color === 'string' && !color.includes('-') && !Color.isValidColorToken(color)) {
5568
+ // Check if the color exists in the palette
5569
+ if (color in palette && color !== 'black' && color !== 'white') {
5570
+ normalizedColor = `${color}-500`;
5571
+ }
5572
+ }
5573
+ const colorRgb = Color.rgb(normalizedColor);
5574
+ if (Color.isValidColorToken(normalizedColor)) {
5424
5575
  // Token-based calculation
5425
- const parts = color.split('-');
5576
+ const parts = normalizedColor.split('-');
5426
5577
  const colorShade = parseInt(parts[1].toString(), 10);
5427
5578
  const shadeMin = 100;
5428
5579
  const shadeMax = 900;
@@ -5455,7 +5606,8 @@
5455
5606
  // Border constants
5456
5607
  const BLACK_BORDER_THICKNESS$7 = 2;
5457
5608
  const WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$7 = 2;
5458
- const WHITE_BORDER_TOTAL_EXTRA_PIXELS$7 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$7 * 2; // 4 pixels total
5609
+ // eslint-disable-next-line no-magic-numbers
5610
+ const WHITE_BORDER_TOTAL_EXTRA_PIXELS$7 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$7 * 3; // 5 pixels total
5459
5611
  const WHITE_BORDER_RADIUS_EXTRA$7 = 2;
5460
5612
  // Overlay constants
5461
5613
  const LIGHT_OVERLAY_SCALE$1 = 0.6;
@@ -5484,7 +5636,7 @@
5484
5636
  const sizePx = typeof size === 'number'
5485
5637
  ? size
5486
5638
  : this.pw.fontSize.px(size ?? 'md');
5487
- const baseColor = color ?? 'gray';
5639
+ const baseColor = color ?? 'blue-500';
5488
5640
  this.sizePx = sizePx;
5489
5641
  this.updateSize();
5490
5642
  this.baseColor = baseColor;
@@ -6694,7 +6846,7 @@
6694
6846
  // Border constants
6695
6847
  const BLACK_BORDER_THICKNESS$5 = 2;
6696
6848
  const WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$5 = 2;
6697
- const WHITE_BORDER_TOTAL_EXTRA_PIXELS$5 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$5 * 2; // 4 pixels total
6849
+ const WHITE_BORDER_TOTAL_EXTRA_PIXELS$5 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$5 * 3; // 6 pixels total
6698
6850
  const WHITE_BORDER_RADIUS_EXTRA$5 = 2;
6699
6851
  /**
6700
6852
  * A flat section header component without gradient overlays, with text stroke and auto-sizing
@@ -7122,8 +7274,8 @@
7122
7274
  var POINTER_DOWN_SCALE$2 = 0.95;
7123
7275
  // Border constants
7124
7276
  var BLACK_BORDER_THICKNESS$4 = 2;
7125
- var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$4 = 2;
7126
- var WHITE_BORDER_TOTAL_EXTRA_PIXELS$4 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$4 * 2; // 4 pixels total
7277
+ var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$4 = 3;
7278
+ var WHITE_BORDER_TOTAL_EXTRA_PIXELS$4 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$4 * 2; // 6 pixels total
7127
7279
  var WHITE_BORDER_RADIUS_EXTRA$4 = 2;
7128
7280
  /**
7129
7281
  * A customizable flat text button component for Phaser, supporting auto-sizing,
@@ -7136,7 +7288,7 @@
7136
7288
  * @param params FlatTextButtonParams
7137
7289
  */
7138
7290
  function FlatTextButton(_a) {
7139
- var scene = _a.scene, x = _a.x, y = _a.y, text = _a.text, _b = _a.fontSize, fontSize = _b === void 0 ? 'lg' : _b, font = _a.font, _c = _a.color, color = _c === void 0 ? 'blue' : _c, _d = _a.textColor, textColor = _d === void 0 ? 'white' : _d, _e = _a.borderRadius, borderRadius = _e === void 0 ? 'md' : _e, _f = _a.padding, padding = _f === void 0 ? '4' : _f, onClick = _a.onClick;
7291
+ var scene = _a.scene, x = _a.x, y = _a.y, text = _a.text, _b = _a.fontSize, fontSize = _b === void 0 ? 'lg' : _b, font = _a.font, _c = _a.color, color = _c === void 0 ? 'blue-500' : _c, _d = _a.textColor, textColor = _d === void 0 ? 'white' : _d, _e = _a.borderRadius, borderRadius = _e === void 0 ? 'md' : _e, _f = _a.padding, padding = _f === void 0 ? '4' : _f, onClick = _a.onClick;
7140
7292
  var _this = _super.call(this, { scene: scene, x: x, y: y }) || this;
7141
7293
  _this.pw = getPWFromScene$1(scene);
7142
7294
  // Store values
@@ -7433,7 +7585,7 @@
7433
7585
  /**
7434
7586
  * Calculates a color variant by adjusting brightness.
7435
7587
  *
7436
- * @param color - The base color (can be a Phaser Wind token like "blue-500" or a CSS color like "#3B82F6")
7588
+ * @param color - The base color (can be a Phaser Wind token like "blue-500", a color name like "red", or a CSS color like "#3B82F6")
7437
7589
  * @param tokenDiff - Amount to adjust the shade for color tokens. Positive values make it darker, negative lighter.
7438
7590
  * For example: -400 for lighter (blue-500 → blue-100), +400 for darker (blue-500 → blue-900)
7439
7591
  * @param colorDiff - Amount to lighten/darken CSS colors. Positive values lighten, negative values darken.
@@ -7441,6 +7593,7 @@
7441
7593
  * @returns The adjusted color as a number
7442
7594
  *
7443
7595
  * @remarks
7596
+ * - If only a color name is provided without a shade (e.g., "red"), it automatically adds "-500" as the default shade
7444
7597
  * - If a color token is provided (e.g., "blue-500"), it uses the token system to calculate variants
7445
7598
  * by adjusting the shade value with tokenDiff (clamped between 100-900)
7446
7599
  * - If a CSS color is provided (hex or rgb), it uses Phaser's lighten/darken methods
@@ -7448,6 +7601,10 @@
7448
7601
  *
7449
7602
  * @example
7450
7603
  * ```typescript
7604
+ * // Using color name only - defaults to -500
7605
+ * const defaultRed = getColorVariant('red', 0, 0);
7606
+ * // Returns red-500 color value
7607
+ *
7451
7608
  * // Using color token - lighter variant
7452
7609
  * const lightBlue = getColorVariant('blue-500', -400, 0);
7453
7610
  * // Returns blue-100 color value
@@ -7466,10 +7623,18 @@
7466
7623
  * ```
7467
7624
  */
7468
7625
  var getColorVariant = function (color, tokenDiff, colorDiff) {
7469
- var colorRgb = Color.rgb(color);
7470
- if (Color.isValidColorToken(color)) {
7626
+ // If only the color name is provided (without shade), validate and add -500 as default
7627
+ var normalizedColor = color;
7628
+ if (typeof color === 'string' && !color.includes('-') && !Color.isValidColorToken(color)) {
7629
+ // Check if the color exists in the palette
7630
+ if (color in palette && color !== 'black' && color !== 'white') {
7631
+ normalizedColor = "".concat(color, "-500");
7632
+ }
7633
+ }
7634
+ var colorRgb = Color.rgb(normalizedColor);
7635
+ if (Color.isValidColorToken(normalizedColor)) {
7471
7636
  // Token-based calculation
7472
- var parts = color.split('-');
7637
+ var parts = normalizedColor.split('-');
7473
7638
  var colorShade = parseInt(parts[1].toString(), 10);
7474
7639
  var shadeMin = 100;
7475
7640
  var shadeMax = 900;
@@ -7500,7 +7665,8 @@
7500
7665
  // Border constants
7501
7666
  var BLACK_BORDER_THICKNESS$3 = 2;
7502
7667
  var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$3 = 2;
7503
- var WHITE_BORDER_TOTAL_EXTRA_PIXELS$3 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$3 * 2; // 4 pixels total
7668
+ // eslint-disable-next-line no-magic-numbers
7669
+ var WHITE_BORDER_TOTAL_EXTRA_PIXELS$3 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$3 * 3; // 5 pixels total
7504
7670
  var WHITE_BORDER_RADIUS_EXTRA$3 = 2;
7505
7671
  // Overlay constants
7506
7672
  var LIGHT_OVERLAY_SCALE = 0.6;
@@ -7521,7 +7687,7 @@
7521
7687
  var sizePx = typeof size === 'number'
7522
7688
  ? size
7523
7689
  : _this.pw.fontSize.px(size !== null && size !== void 0 ? size : 'md');
7524
- var baseColor = color !== null && color !== void 0 ? color : 'gray';
7690
+ var baseColor = color !== null && color !== void 0 ? color : 'blue-500';
7525
7691
  _this.sizePx = sizePx;
7526
7692
  _this.updateSize();
7527
7693
  _this.baseColor = baseColor;
@@ -8701,7 +8867,7 @@
8701
8867
  // Border constants
8702
8868
  var BLACK_BORDER_THICKNESS$1 = 2;
8703
8869
  var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$1 = 2;
8704
- var WHITE_BORDER_TOTAL_EXTRA_PIXELS$1 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$1 * 2; // 4 pixels total
8870
+ var WHITE_BORDER_TOTAL_EXTRA_PIXELS$1 = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE$1 * 3; // 6 pixels total
8705
8871
  var WHITE_BORDER_RADIUS_EXTRA$1 = 2;
8706
8872
  /**
8707
8873
  * A flat section header component without gradient overlays, with text stroke and auto-sizing
@@ -9016,8 +9182,8 @@
9016
9182
  var COLOR_DARKER_AMOUNT = -30;
9017
9183
  // Border constants
9018
9184
  var BLACK_BORDER_THICKNESS = 2;
9019
- var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE = 2;
9020
- var WHITE_BORDER_TOTAL_EXTRA_PIXELS = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE * 2; // 4 pixels total
9185
+ var WHITE_BORDER_EXTRA_PIXELS_PER_SIDE = 3;
9186
+ var WHITE_BORDER_TOTAL_EXTRA_PIXELS = WHITE_BORDER_EXTRA_PIXELS_PER_SIDE * 2; // 6 pixels total
9021
9187
  var WHITE_BORDER_RADIUS_EXTRA = 2;
9022
9188
  /**
9023
9189
  * A customizable text button component for Phaser, supporting auto-sizing,
@@ -9030,7 +9196,7 @@
9030
9196
  * @param params TextButtonParams
9031
9197
  */
9032
9198
  function TextButton(_a) {
9033
- var scene = _a.scene, x = _a.x, y = _a.y, text = _a.text, _b = _a.fontSize, fontSize = _b === void 0 ? 'lg' : _b, font = _a.font, _c = _a.color, color = _c === void 0 ? 'blue' : _c, _d = _a.textColor, textColor = _d === void 0 ? 'white' : _d, _e = _a.borderRadius, borderRadius = _e === void 0 ? 'md' : _e, _f = _a.padding, padding = _f === void 0 ? '4' : _f, onClick = _a.onClick;
9199
+ var scene = _a.scene, x = _a.x, y = _a.y, text = _a.text, _b = _a.fontSize, fontSize = _b === void 0 ? 'lg' : _b, font = _a.font, _c = _a.color, color = _c === void 0 ? 'blue-500' : _c, _d = _a.textColor, textColor = _d === void 0 ? 'white' : _d, _e = _a.borderRadius, borderRadius = _e === void 0 ? 'md' : _e, _f = _a.padding, padding = _f === void 0 ? '4' : _f, onClick = _a.onClick;
9034
9200
  var _this = _super.call(this, { scene: scene, x: x, y: y }) || this;
9035
9201
  _this.pw = getPWFromScene$1(scene);
9036
9202
  // Store values
@@ -9475,10 +9641,33 @@
9475
9641
  return HudiniPlugin;
9476
9642
  }(Phaser$1.Plugins.BasePlugin));
9477
9643
 
9644
+ /**
9645
+ * @deprecated Use {@link withHudini} instead.
9646
+ *
9647
+ * Forces single inheritance, which conflicts with any user-defined `BaseScene`
9648
+ * or other libraries that ship their own scene base class. It also relies on a
9649
+ * non-null assertion (`hudini!`) that lies to TypeScript about when the plugin
9650
+ * is available — touching `this.hudini` before the plugin mounts throws at
9651
+ * runtime.
9652
+ *
9653
+ * Prefer the `withHudini(scene)` accessor:
9654
+ *
9655
+ * ```ts
9656
+ * import { withHudini } from 'hudini';
9657
+ * import type { ThemeType } from './theme';
9658
+ *
9659
+ * class MyScene extends Phaser.Scene {
9660
+ * create() {
9661
+ * const hudini = withHudini<ThemeType>(this);
9662
+ * }
9663
+ * }
9664
+ * ```
9665
+ *
9666
+ * Kept exported to avoid breaking existing consumers.
9667
+ */
9478
9668
  var SceneWithHudini = /** @class */ (function (_super) {
9479
9669
  __extends(SceneWithHudini, _super);
9480
9670
  /**
9481
- *
9482
9671
  * @param config The scene key or scene specific configuration settings.
9483
9672
  */
9484
9673
  function SceneWithHudini(config) {
@@ -9487,6 +9676,40 @@
9487
9676
  return SceneWithHudini;
9488
9677
  }(SceneWithPhaserWind));
9489
9678
 
9679
+ /**
9680
+ * Accessor for the Hudini plugin from within a Phaser scene.
9681
+ *
9682
+ * Preferred over {@link SceneWithHudini} (inheritance) and over module
9683
+ * augmentation of `Phaser.Scene`, because it:
9684
+ * - Composes with any existing base scene (no forced inheritance).
9685
+ * - Keeps the theme type explicit at the call site (no silent `any`).
9686
+ * - Doesn't rely on non-null assertions that lie about lifecycle.
9687
+ *
9688
+ * Call it inside `create()` / `update()` (after the plugin has been installed).
9689
+ *
9690
+ * @typeParam T - The theme config type. Pass your `ThemeType` to get
9691
+ * type-narrowed access to your custom tokens (through `hudini.pw`).
9692
+ * @param scene - The Phaser scene instance.
9693
+ * @returns The Hudini plugin instance bound to the given theme type.
9694
+ *
9695
+ * @example
9696
+ * ```ts
9697
+ * import { withHudini } from 'hudini';
9698
+ * import type { ThemeType } from './theme';
9699
+ *
9700
+ * class MyScene extends Phaser.Scene {
9701
+ * create() {
9702
+ * const hudini = withHudini<ThemeType>(this);
9703
+ * const pw = hudini.pw;
9704
+ * this.cameras.main.setBackgroundColor(pw.color.rgb('background'));
9705
+ * }
9706
+ * }
9707
+ * ```
9708
+ */
9709
+ var withHudini = function (scene) {
9710
+ return scene.plugins.get(HUDINI_KEY);
9711
+ };
9712
+
9490
9713
  var getHudini = function (scene) {
9491
9714
  return scene.hudini;
9492
9715
  };
@@ -9505,6 +9728,7 @@
9505
9728
  exports.HudiniPlugin = HudiniPlugin;
9506
9729
  exports.IconButton = IconButton;
9507
9730
  exports.LinearProgress = LinearProgress;
9731
+ exports.Opacity = Opacity;
9508
9732
  exports.PHASER_WIND_KEY = PHASER_WIND_KEY;
9509
9733
  exports.Panel = Panel;
9510
9734
  exports.PhaserWindPlugin = PhaserWindPlugin;
@@ -9522,6 +9746,7 @@
9522
9746
  exports.createColor = createColor;
9523
9747
  exports.createFont = createFont;
9524
9748
  exports.createFontSize = createFontSize;
9749
+ exports.createOpacity = createOpacity;
9525
9750
  exports.createRadius = createRadius;
9526
9751
  exports.createShadow = createShadow;
9527
9752
  exports.createSpacing = createSpacing;
@@ -9541,8 +9766,11 @@
9541
9766
  exports.loadFonts = loadFonts;
9542
9767
  exports.merge = merge;
9543
9768
  exports.mergeDeep = mergeDeep;
9769
+ exports.opacityMap = opacityMap;
9544
9770
  exports.palette = palette;
9545
9771
  exports.radiusMap = radiusMap;
9546
9772
  exports.spacingMap = spacingMap;
9773
+ exports.withHudini = withHudini;
9774
+ exports.withPhaserWind = withPhaserWind;
9547
9775
 
9548
9776
  }));