@trops/dash-core 0.1.574 → 0.1.575

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
@@ -34676,11 +34676,8 @@ var ThemePickerGridPane = function ThemePickerGridPane(_ref) {
34676
34676
  }
34677
34677
  return /*#__PURE__*/jsxRuntime.jsx(ThemePane, {
34678
34678
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
34679
- className: "flex flex-row rounded overflow-clip justify-center items-center align-center w-full",
34680
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
34681
- className: "grid grid-cols-3 gap-4 w-full h-full overflow-y-scroll scrollbar scrollbar-thumb-gray-700 scrollbar-thin scrollbar-track-transparent",
34682
- children: renderCurrentThemes()
34683
- })
34679
+ className: "grid grid-cols-3 gap-4 w-full flex-1 min-h-0 overflow-y-auto pr-2 scrollbar scrollbar-thumb-gray-700 scrollbar-thin scrollbar-track-transparent",
34680
+ children: renderCurrentThemes()
34684
34681
  })
34685
34682
  });
34686
34683
  };
@@ -36924,12 +36921,85 @@ var PanelThemeStudio = function PanelThemeStudio(_ref) {
36924
36921
  });
36925
36922
  };
36926
36923
 
36927
- /**
36928
- * themeGenerator.js
36929
- *
36930
- * Utility for generating themes via presets, random generation,
36931
- * and color-harmony-based generation from a user-selected base color.
36932
- */
36924
+ // Color harmony helpers — inlined so dash-core can ship the new
36925
+ // "From Colors" generator without first publishing matching
36926
+ // exports from @trops/dash-react. Same math as the planned dash-react
36927
+ // counterparts; can be replaced with a re-export once both ship in
36928
+ // the same cycle.
36929
+ function rotateHex(hex, deltaH) {
36930
+ var rgb = DashReact.hexToRgb(hex);
36931
+ if (!rgb) return null;
36932
+ var _rgbToHsl = DashReact.rgbToHsl(rgb),
36933
+ h = _rgbToHsl.h,
36934
+ s = _rgbToHsl.s,
36935
+ l = _rgbToHsl.l;
36936
+ var newH = ((h + deltaH) % 360 + 360) % 360;
36937
+ return DashReact.rgbToHex(DashReact.hslToRgb({
36938
+ h: newH,
36939
+ s: s,
36940
+ l: l
36941
+ }));
36942
+ }
36943
+ function complementHex(hex) {
36944
+ return rotateHex(hex, 180);
36945
+ }
36946
+ function analogousHexes(hex) {
36947
+ var a = rotateHex(hex, -30);
36948
+ var b = rotateHex(hex, 30);
36949
+ return a && b ? [a, b] : null;
36950
+ }
36951
+ function triadicHexes(hex) {
36952
+ var a = rotateHex(hex, 120);
36953
+ var b = rotateHex(hex, 240);
36954
+ return a && b ? [a, b] : null;
36955
+ }
36956
+ function splitComplementaryHexes(hex) {
36957
+ var a = rotateHex(hex, 150);
36958
+ var b = rotateHex(hex, 210);
36959
+ return a && b ? [a, b] : null;
36960
+ }
36961
+ function tetradicHexes(hex) {
36962
+ var a = rotateHex(hex, 90);
36963
+ var b = rotateHex(hex, 180);
36964
+ var c = rotateHex(hex, 270);
36965
+ return a && b && c ? [a, b, c] : null;
36966
+ }
36967
+ function monochromaticHexes(hex) {
36968
+ var count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
36969
+ var rgb = DashReact.hexToRgb(hex);
36970
+ if (!rgb) return null;
36971
+ var _rgbToHsl2 = DashReact.rgbToHsl(rgb),
36972
+ h = _rgbToHsl2.h,
36973
+ s = _rgbToHsl2.s;
36974
+ var out = [];
36975
+ for (var i = 0; i < count; i++) {
36976
+ var t = count === 1 ? 0.5 : i / (count - 1);
36977
+ var l = 0.15 + t * 0.7;
36978
+ var sAdj = s * (1 - 0.3 * Math.abs(t - 0.5) * 2);
36979
+ out.push(DashReact.rgbToHex(DashReact.hslToRgb({
36980
+ h: h,
36981
+ s: sAdj,
36982
+ l: l
36983
+ })));
36984
+ }
36985
+ return out;
36986
+ }
36987
+ function adjustHsl(hex) {
36988
+ var dH = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
36989
+ var dS = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
36990
+ var dL = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
36991
+ var rgb = DashReact.hexToRgb(hex);
36992
+ if (!rgb) return null;
36993
+ var hsl = DashReact.rgbToHsl(rgb);
36994
+ var h = ((hsl.h + dH) % 360 + 360) % 360;
36995
+ var s = Math.max(0, Math.min(1, hsl.s + dS));
36996
+ var l = Math.max(0, Math.min(1, hsl.l + dL));
36997
+ return DashReact.rgbToHex(DashReact.hslToRgb({
36998
+ h: h,
36999
+ s: s,
37000
+ l: l
37001
+ }));
37002
+ }
36933
37003
 
36934
37004
  // Color wheel mapping for Tailwind palettes (approximate hue angles)
36935
37005
  var COLOR_WHEEL = {
@@ -37097,11 +37167,22 @@ function generateRandomTheme() {
37097
37167
 
37098
37168
  /**
37099
37169
  * Generate a theme using color harmony rules from a base color.
37100
- * @param {string} baseColor - A Tailwind color name (e.g. "blue")
37101
- * @param {"complementary"|"analogous"|"triadic"|"split-complementary"} strategy
37170
+ * Accepts either a Tailwind color name OR a hex string. Hex bases
37171
+ * run through dash-react's harmony math and emit hex channels for
37172
+ * every output; named bases use the legacy COLOR_WHEEL mapping.
37173
+ *
37174
+ * @param {string} baseColor - Tailwind color name (e.g. "blue") OR hex
37175
+ * @param {"complementary"|"analogous"|"triadic"|"split-complementary"|"tetradic"|"monochromatic"} strategy
37176
+ * @param {{ dH?: number, dS?: number, dL?: number }} [hslNudge] - optional
37177
+ * HSL offsets applied to every generated channel after the harmony
37178
+ * math. dH in degrees; dS/dL as fractions in [-1..1].
37102
37179
  */
37103
37180
  function generateHarmonyTheme(baseColor) {
37104
37181
  var strategy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "complementary";
37182
+ var hslNudge = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
37183
+ if (typeof baseColor === "string" && DashReact.isHexColor(baseColor)) {
37184
+ return generateHexHarmonyTheme(baseColor, strategy, hslNudge);
37185
+ }
37105
37186
  var baseHue = COLOR_WHEEL[baseColor];
37106
37187
  if (baseHue === undefined) {
37107
37188
  return generateRandomTheme();
@@ -37137,17 +37218,114 @@ function generateHarmonyTheme(baseColor) {
37137
37218
  }
37138
37219
 
37139
37220
  /**
37140
- * Generate a theme from three independently chosen colors.
37141
- * @param {string} primary - A Tailwind color name
37142
- * @param {string} secondary - A Tailwind color name
37143
- * @param {string} tertiary - A Tailwind color name
37221
+ * Hex-mode harmony generation. Always emits hex channels; supports
37222
+ * all the named harmony strategies plus Monochromatic and Tetradic.
37223
+ * The neutral channel is derived from the base by desaturating
37224
+ * almost fully, keeping the same hue family for a cohesive feel.
37144
37225
  */
37145
- function generateCustomTheme(primary, secondary, tertiary) {
37146
- var neutral = pick(NEUTRAL_COLORS);
37226
+ function generateHexHarmonyTheme(baseHex, strategy, hslNudge) {
37227
+ var base = DashReact.normalizeHex(baseHex);
37228
+ if (!base) return generateRandomTheme();
37229
+ var primary = base;
37230
+ var secondary;
37231
+ var tertiary;
37232
+ var neutral;
37233
+ switch (strategy) {
37234
+ case "complementary":
37235
+ {
37236
+ secondary = complementHex(base);
37237
+ var ana = analogousHexes(base);
37238
+ tertiary = ana ? ana[1] : base;
37239
+ break;
37240
+ }
37241
+ case "analogous":
37242
+ {
37243
+ var _ana = analogousHexes(base);
37244
+ if (_ana) {
37245
+ secondary = _ana[0];
37246
+ tertiary = _ana[1];
37247
+ }
37248
+ break;
37249
+ }
37250
+ case "triadic":
37251
+ {
37252
+ var tri = triadicHexes(base);
37253
+ if (tri) {
37254
+ secondary = tri[0];
37255
+ tertiary = tri[1];
37256
+ }
37257
+ break;
37258
+ }
37259
+ case "split-complementary":
37260
+ {
37261
+ var split = splitComplementaryHexes(base);
37262
+ if (split) {
37263
+ secondary = split[0];
37264
+ tertiary = split[1];
37265
+ }
37266
+ break;
37267
+ }
37268
+ case "tetradic":
37269
+ {
37270
+ var tet = tetradicHexes(base);
37271
+ if (tet) {
37272
+ secondary = tet[0];
37273
+ tertiary = tet[1];
37274
+ neutral = tet[2];
37275
+ }
37276
+ break;
37277
+ }
37278
+ case "monochromatic":
37279
+ {
37280
+ var mono = monochromaticHexes(base, 3);
37281
+ if (mono) {
37282
+ primary = mono[1];
37283
+ secondary = mono[0];
37284
+ tertiary = mono[2];
37285
+ }
37286
+ break;
37287
+ }
37288
+ default:
37289
+ {
37290
+ secondary = complementHex(base);
37291
+ var _ana2 = analogousHexes(base);
37292
+ tertiary = _ana2 ? _ana2[1] : base;
37293
+ }
37294
+ }
37295
+
37296
+ // Neutral defaults to a near-grey of the same hue (desaturated).
37297
+ if (!neutral) {
37298
+ neutral = adjustHsl(base, 0, -0.85, 0);
37299
+ }
37300
+
37301
+ // Apply optional HSL nudge uniformly to all channels.
37302
+ if (hslNudge) {
37303
+ var _hslNudge$dH = hslNudge.dH,
37304
+ dH = _hslNudge$dH === void 0 ? 0 : _hslNudge$dH,
37305
+ _hslNudge$dS = hslNudge.dS,
37306
+ dS = _hslNudge$dS === void 0 ? 0 : _hslNudge$dS,
37307
+ _hslNudge$dL = hslNudge.dL,
37308
+ dL = _hslNudge$dL === void 0 ? 0 : _hslNudge$dL;
37309
+ primary = adjustHsl(primary, dH, dS, dL) || primary;
37310
+ secondary = adjustHsl(secondary, dH, dS, dL) || secondary;
37311
+ tertiary = adjustHsl(tertiary, dH, dS, dL) || tertiary;
37312
+ neutral = adjustHsl(neutral, dH, dS, dL) || neutral;
37313
+ }
37147
37314
  var name = generateThemeName(primary, secondary);
37148
37315
  return buildRawTheme(name, primary, secondary, tertiary, neutral);
37149
37316
  }
37150
37317
 
37318
+ /**
37319
+ * Generate a theme from four independently chosen channel values.
37320
+ * Each channel may be a Tailwind name or a hex string.
37321
+ */
37322
+ function generateCustomTheme(primary, secondary, tertiary) {
37323
+ var neutral = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
37324
+ var resolvedNeutral = neutral || pick(NEUTRAL_COLORS);
37325
+ var name = generateThemeName(primary, secondary);
37326
+ return buildRawTheme(name, primary, secondary, tertiary, resolvedNeutral);
37327
+ }
37328
+
37151
37329
  /**
37152
37330
  * All available chromatic colors for the "From Color" picker.
37153
37331
  */
@@ -37168,6 +37346,12 @@ var HARMONY_STRATEGIES = [{
37168
37346
  }, {
37169
37347
  value: "split-complementary",
37170
37348
  label: "Split Complementary"
37349
+ }, {
37350
+ value: "tetradic",
37351
+ label: "Tetradic"
37352
+ }, {
37353
+ value: "monochromatic",
37354
+ label: "Monochromatic"
37171
37355
  }, {
37172
37356
  value: "custom",
37173
37357
  label: "Custom"
@@ -37266,87 +37450,165 @@ var PresetGallery = function PresetGallery(_ref3) {
37266
37450
 
37267
37451
  // ─── Color Harmony Picker ────────────────────────────────────────────────
37268
37452
 
37269
- var ColorSwatchGrid$1 = function ColorSwatchGrid(_ref4) {
37453
+ /**
37454
+ * Render a swatch for a generated palette channel. Hex values render
37455
+ * inline; named Tailwind families fall back to `bg-{name}-500` which
37456
+ * is in the safelist.
37457
+ */
37458
+ var PaletteSwatch = function PaletteSwatch(_ref4) {
37270
37459
  var value = _ref4.value,
37271
- onChange = _ref4.onChange,
37272
37460
  label = _ref4.label;
37461
+ var isHex = DashReact.isHexColor(value);
37273
37462
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
37274
- className: "flex flex-col gap-2",
37275
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37276
- className: "text-xs opacity-50",
37463
+ className: "flex flex-col items-center gap-1 flex-1",
37464
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37465
+ className: "h-10 w-full rounded ".concat(isHex ? "" : "bg-".concat(value, "-500")),
37466
+ style: isHex ? {
37467
+ backgroundColor: value
37468
+ } : undefined
37469
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
37470
+ className: "text-xs opacity-60 truncate w-full text-center",
37277
37471
  children: label
37472
+ })]
37473
+ });
37474
+ };
37475
+
37476
+ /**
37477
+ * Compact hex picker reused inline by the wizard. Category chips +
37478
+ * a curated grid of swatches + a custom-hex input below. Same
37479
+ * primitives as ChannelEditorModal but laid out for a narrower
37480
+ * column.
37481
+ */
37482
+ var InlineHexPicker = function InlineHexPicker(_ref5) {
37483
+ var selectedHex = _ref5.selectedHex,
37484
+ onPick = _ref5.onPick;
37485
+ var families = DashReact.getColorFamilies();
37486
+ var _useState = React.useState(families[0]),
37487
+ _useState2 = _slicedToArray(_useState, 2),
37488
+ activeFamily = _useState2[0],
37489
+ setActiveFamily = _useState2[1];
37490
+ var swatches = DashReact.getCuratedColorGrid(activeFamily);
37491
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
37492
+ className: "flex flex-col gap-2",
37493
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37494
+ className: "flex flex-row gap-2 flex-wrap",
37495
+ children: families.map(function (family) {
37496
+ var isActive = activeFamily === family;
37497
+ return /*#__PURE__*/jsxRuntime.jsx("button", {
37498
+ type: "button",
37499
+ onClick: function onClick() {
37500
+ return setActiveFamily(family);
37501
+ },
37502
+ className: "px-2 py-0.5 rounded-full text-xs font-medium ".concat(isActive ? "bg-blue-600 text-white" : "bg-gray-700 text-gray-300 hover:bg-gray-600"),
37503
+ children: family
37504
+ }, family);
37505
+ })
37278
37506
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
37279
- className: "grid grid-cols-6 gap-2",
37280
- children: AVAILABLE_COLORS.map(function (color) {
37281
- return /*#__PURE__*/jsxRuntime.jsx("div", {
37282
- className: "h-8 rounded cursor-pointer transition-all bg-".concat(color, "-500 ").concat(value === color ? "ring-2 ring-white scale-110" : "opacity-70 hover:opacity-100"),
37283
- title: color,
37507
+ className: "grid grid-cols-12 gap-1",
37508
+ children: swatches.map(function (hex) {
37509
+ var isSelected = selectedHex && hex.toLowerCase() === selectedHex.toLowerCase();
37510
+ return /*#__PURE__*/jsxRuntime.jsx("button", {
37511
+ type: "button",
37284
37512
  onClick: function onClick() {
37285
- return onChange(color);
37286
- }
37287
- }, color);
37513
+ return onPick(hex);
37514
+ },
37515
+ style: {
37516
+ backgroundColor: hex
37517
+ },
37518
+ className: "h-6 rounded transition-transform hover:scale-110 ".concat(isSelected ? "border-2 border-yellow-400 scale-110" : ""),
37519
+ "aria-label": "Pick ".concat(hex),
37520
+ title: hex
37521
+ }, hex);
37288
37522
  })
37523
+ }), /*#__PURE__*/jsxRuntime.jsx(CustomHexColorPane, {
37524
+ onApply: onPick,
37525
+ label: "Or paste a hex value"
37289
37526
  })]
37290
37527
  });
37291
37528
  };
37292
- var PreviewSwatch = function PreviewSwatch(_ref5) {
37293
- var color = _ref5.color,
37294
- strategy = _ref5.strategy,
37295
- customColors = _ref5.customColors;
37296
- var colors;
37297
- if (strategy === "custom" && customColors) {
37298
- colors = [customColors.primary, customColors.secondary, customColors.tertiary];
37299
- } else {
37300
- var theme = generateHarmonyTheme(color, strategy);
37301
- colors = [theme.primary, theme.secondary, theme.tertiary];
37302
- }
37303
- return /*#__PURE__*/jsxRuntime.jsx("div", {
37304
- className: "flex flex-row gap-2",
37305
- children: colors.map(function (c, i) {
37306
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
37307
- className: "flex flex-col items-center gap-1 flex-1",
37308
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37309
- className: "h-10 w-full rounded bg-".concat(c, "-500")
37310
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
37311
- className: "text-[10px] opacity-40",
37312
- children: c
37313
- })]
37314
- }, i);
37315
- })
37529
+
37530
+ /**
37531
+ * HSL nudge slider — single-axis. Display label + numeric value.
37532
+ */
37533
+ var HslSlider = function HslSlider(_ref6) {
37534
+ var label = _ref6.label,
37535
+ value = _ref6.value,
37536
+ min = _ref6.min,
37537
+ max = _ref6.max,
37538
+ step = _ref6.step,
37539
+ _onChange = _ref6.onChange,
37540
+ _ref6$unit = _ref6.unit,
37541
+ unit = _ref6$unit === void 0 ? "" : _ref6$unit;
37542
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
37543
+ className: "flex flex-col gap-1",
37544
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37545
+ className: "flex flex-row items-center justify-between",
37546
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37547
+ className: "text-xs opacity-60",
37548
+ children: label
37549
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
37550
+ className: "text-xs opacity-50 font-mono",
37551
+ children: [value > 0 ? "+".concat(value) : value, unit]
37552
+ })]
37553
+ }), /*#__PURE__*/jsxRuntime.jsx("input", {
37554
+ type: "range",
37555
+ min: min,
37556
+ max: max,
37557
+ step: step,
37558
+ value: value,
37559
+ onChange: function onChange(e) {
37560
+ return _onChange(parseFloat(e.target.value));
37561
+ },
37562
+ className: "w-full accent-blue-500"
37563
+ })]
37316
37564
  });
37317
37565
  };
37318
- var ColorHarmonyPicker = function ColorHarmonyPicker(_ref6) {
37319
- var onGenerate = _ref6.onGenerate,
37320
- _ref6$inline = _ref6.inline,
37321
- inline = _ref6$inline === void 0 ? false : _ref6$inline;
37322
- var _useState = React.useState("blue"),
37323
- _useState2 = _slicedToArray(_useState, 2),
37324
- selectedColor = _useState2[0],
37325
- setSelectedColor = _useState2[1];
37326
- var _useState3 = React.useState("rose"),
37566
+ var ColorHarmonyPicker = function ColorHarmonyPicker(_ref7) {
37567
+ var onGenerate = _ref7.onGenerate,
37568
+ _ref7$inline = _ref7.inline,
37569
+ inline = _ref7$inline === void 0 ? false : _ref7$inline;
37570
+ // Default to a brand-blue hex so the wizard opens in hex mode.
37571
+ var _useState3 = React.useState("#3b82f6"),
37327
37572
  _useState4 = _slicedToArray(_useState3, 2),
37328
- secondaryColor = _useState4[0],
37329
- setSecondaryColor = _useState4[1];
37330
- var _useState5 = React.useState("amber"),
37573
+ selectedColor = _useState4[0],
37574
+ setSelectedColor = _useState4[1];
37575
+ var _useState5 = React.useState("complementary"),
37331
37576
  _useState6 = _slicedToArray(_useState5, 2),
37332
- tertiaryColor = _useState6[0],
37333
- setTertiaryColor = _useState6[1];
37334
- var _useState7 = React.useState("complementary"),
37577
+ strategy = _useState6[0],
37578
+ setStrategy = _useState6[1];
37579
+ // HSL nudge — applied to every generated channel after harmony math.
37580
+ var _useState7 = React.useState(0),
37335
37581
  _useState8 = _slicedToArray(_useState7, 2),
37336
- strategy = _useState8[0],
37337
- setStrategy = _useState8[1];
37338
- var isCustom = strategy === "custom";
37582
+ dH = _useState8[0],
37583
+ setDH = _useState8[1];
37584
+ var _useState9 = React.useState(0),
37585
+ _useState0 = _slicedToArray(_useState9, 2),
37586
+ dS = _useState0[0],
37587
+ setDS = _useState0[1];
37588
+ var _useState1 = React.useState(0),
37589
+ _useState10 = _slicedToArray(_useState1, 2),
37590
+ dL = _useState10[0],
37591
+ setDL = _useState10[1];
37592
+
37593
+ // Generate the current theme from inputs. Memoized through useEffect
37594
+ // for the inline-preview path; explicit handler for the button path.
37595
+ function buildTheme() {
37596
+ return generateHarmonyTheme(selectedColor, strategy, {
37597
+ dH: dH,
37598
+ dS: dS,
37599
+ dL: dL
37600
+ });
37601
+ }
37339
37602
  React.useEffect(function () {
37340
37603
  if (inline) {
37341
- var theme = isCustom ? generateCustomTheme(selectedColor, secondaryColor, tertiaryColor) : generateHarmonyTheme(selectedColor, strategy);
37342
- onGenerate(theme);
37604
+ onGenerate(buildTheme());
37343
37605
  }
37344
37606
  // eslint-disable-next-line react-hooks/exhaustive-deps
37345
- }, [selectedColor, secondaryColor, tertiaryColor, strategy, inline]);
37607
+ }, [selectedColor, strategy, dH, dS, dL, inline]);
37346
37608
  function handleGenerate() {
37347
- var theme = isCustom ? generateCustomTheme(selectedColor, secondaryColor, tertiaryColor) : generateHarmonyTheme(selectedColor, strategy);
37348
- onGenerate(theme);
37609
+ onGenerate(buildTheme());
37349
37610
  }
37611
+ var previewTheme = buildTheme();
37350
37612
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
37351
37613
  className: inline ? "flex flex-col gap-4" : "flex flex-col gap-4 p-6 overflow-y-auto flex-1 min-h-0",
37352
37614
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
@@ -37359,7 +37621,9 @@ var ColorHarmonyPicker = function ColorHarmonyPicker(_ref6) {
37359
37621
  children: "Harmony"
37360
37622
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
37361
37623
  className: "flex flex-row gap-2 flex-wrap",
37362
- children: HARMONY_STRATEGIES.map(function (s) {
37624
+ children: HARMONY_STRATEGIES.filter(function (s) {
37625
+ return s.value !== "custom";
37626
+ }).map(function (s) {
37363
37627
  return /*#__PURE__*/jsxRuntime.jsx("button", {
37364
37628
  type: "button",
37365
37629
  className: "px-3 py-1.5 rounded text-xs transition-all ".concat(strategy === s.value ? "bg-blue-600 text-white" : "bg-white/10 opacity-70 hover:opacity-100"),
@@ -37370,37 +37634,71 @@ var ColorHarmonyPicker = function ColorHarmonyPicker(_ref6) {
37370
37634
  }, s.value);
37371
37635
  })
37372
37636
  })]
37373
- }), isCustom ? /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
37374
- children: [/*#__PURE__*/jsxRuntime.jsx(ColorSwatchGrid$1, {
37375
- value: selectedColor,
37376
- onChange: setSelectedColor,
37377
- label: "Primary"
37378
- }), /*#__PURE__*/jsxRuntime.jsx(ColorSwatchGrid$1, {
37379
- value: secondaryColor,
37380
- onChange: setSecondaryColor,
37381
- label: "Secondary"
37382
- }), /*#__PURE__*/jsxRuntime.jsx(ColorSwatchGrid$1, {
37383
- value: tertiaryColor,
37384
- onChange: setTertiaryColor,
37385
- label: "Tertiary"
37637
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37638
+ className: "flex flex-col gap-2",
37639
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37640
+ className: "text-xs opacity-50",
37641
+ children: "Base Color"
37642
+ }), /*#__PURE__*/jsxRuntime.jsx(InlineHexPicker, {
37643
+ selectedHex: DashReact.isHexColor(selectedColor) ? selectedColor : null,
37644
+ onPick: function onPick(hex) {
37645
+ return setSelectedColor(hex);
37646
+ }
37647
+ })]
37648
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37649
+ className: "flex flex-col gap-3",
37650
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37651
+ className: "text-xs opacity-50",
37652
+ children: "Fine-tune (HSL nudge)"
37653
+ }), /*#__PURE__*/jsxRuntime.jsx(HslSlider, {
37654
+ label: "Hue",
37655
+ value: dH,
37656
+ min: -180,
37657
+ max: 180,
37658
+ step: 1,
37659
+ unit: "\xB0",
37660
+ onChange: setDH
37661
+ }), /*#__PURE__*/jsxRuntime.jsx(HslSlider, {
37662
+ label: "Saturation",
37663
+ value: Math.round(dS * 100),
37664
+ min: -100,
37665
+ max: 100,
37666
+ step: 1,
37667
+ unit: "%",
37668
+ onChange: function onChange(v) {
37669
+ return setDS(v / 100);
37670
+ }
37671
+ }), /*#__PURE__*/jsxRuntime.jsx(HslSlider, {
37672
+ label: "Lightness",
37673
+ value: Math.round(dL * 100),
37674
+ min: -100,
37675
+ max: 100,
37676
+ step: 1,
37677
+ unit: "%",
37678
+ onChange: function onChange(v) {
37679
+ return setDL(v / 100);
37680
+ }
37386
37681
  })]
37387
- }) : /*#__PURE__*/jsxRuntime.jsx(ColorSwatchGrid$1, {
37388
- value: selectedColor,
37389
- onChange: setSelectedColor,
37390
- label: "Base Color"
37391
37682
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37392
37683
  className: "flex flex-col gap-2",
37393
37684
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37394
37685
  className: "text-xs opacity-50",
37395
- children: "Preview"
37396
- }), /*#__PURE__*/jsxRuntime.jsx(PreviewSwatch, {
37397
- color: selectedColor,
37398
- strategy: strategy,
37399
- customColors: isCustom ? {
37400
- primary: selectedColor,
37401
- secondary: secondaryColor,
37402
- tertiary: tertiaryColor
37403
- } : null
37686
+ children: "Generated Palette"
37687
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37688
+ className: "flex flex-row gap-2",
37689
+ children: [/*#__PURE__*/jsxRuntime.jsx(PaletteSwatch, {
37690
+ value: previewTheme.primary,
37691
+ label: "Primary"
37692
+ }), /*#__PURE__*/jsxRuntime.jsx(PaletteSwatch, {
37693
+ value: previewTheme.secondary,
37694
+ label: "Secondary"
37695
+ }), /*#__PURE__*/jsxRuntime.jsx(PaletteSwatch, {
37696
+ value: previewTheme.tertiary,
37697
+ label: "Tertiary"
37698
+ }), /*#__PURE__*/jsxRuntime.jsx(PaletteSwatch, {
37699
+ value: previewTheme.neutral,
37700
+ label: "Neutral"
37701
+ })]
37404
37702
  })]
37405
37703
  }), !inline && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37406
37704
  title: "Generate Theme",
@@ -37412,12 +37710,12 @@ var ColorHarmonyPicker = function ColorHarmonyPicker(_ref6) {
37412
37710
 
37413
37711
  // ─── Wizard Components ──────────────────────────────────────────────────
37414
37712
 
37415
- var MethodCard = function MethodCard(_ref7) {
37416
- var icon = _ref7.icon,
37417
- title = _ref7.title,
37418
- subtitle = _ref7.subtitle,
37419
- selected = _ref7.selected,
37420
- onClick = _ref7.onClick;
37713
+ var MethodCard = function MethodCard(_ref8) {
37714
+ var icon = _ref8.icon,
37715
+ title = _ref8.title,
37716
+ subtitle = _ref8.subtitle,
37717
+ selected = _ref8.selected,
37718
+ onClick = _ref8.onClick;
37421
37719
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
37422
37720
  className: "flex flex-col gap-1.5 p-3 rounded-lg cursor-pointer transition-all bg-white/5 hover:bg-white/10 ".concat(selected ? "ring-2 ring-blue-500 bg-white/10" : "hover:ring-1 hover:ring-white/20"),
37423
37721
  onClick: onClick,
@@ -37436,9 +37734,9 @@ var MethodCard = function MethodCard(_ref7) {
37436
37734
  })]
37437
37735
  });
37438
37736
  };
37439
- var RandomPreview = function RandomPreview(_ref8) {
37440
- var theme = _ref8.theme,
37441
- onRegenerate = _ref8.onRegenerate;
37737
+ var RandomPreview = function RandomPreview(_ref9) {
37738
+ var theme = _ref9.theme,
37739
+ onRegenerate = _ref9.onRegenerate;
37442
37740
  var colors = theme ? [theme.primary, theme.secondary, theme.tertiary] : [];
37443
37741
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
37444
37742
  className: "flex flex-col gap-4",
@@ -37465,20 +37763,20 @@ var RandomPreview = function RandomPreview(_ref8) {
37465
37763
  })]
37466
37764
  });
37467
37765
  };
37468
- var ThemeQuickCreate = function ThemeQuickCreate(_ref9) {
37469
- var wizardName = _ref9.wizardName,
37470
- setWizardName = _ref9.setWizardName,
37471
- wizardMethod = _ref9.wizardMethod,
37472
- setWizardMethod = _ref9.setWizardMethod,
37473
- wizardTheme = _ref9.wizardTheme,
37474
- setWizardTheme = _ref9.setWizardTheme,
37475
- onComplete = _ref9.onComplete,
37476
- _ref9$onExtract = _ref9.onExtract,
37477
- onExtract = _ref9$onExtract === void 0 ? null : _ref9$onExtract,
37478
- _ref9$onMapToTheme = _ref9.onMapToTheme,
37479
- onMapToTheme = _ref9$onMapToTheme === void 0 ? null : _ref9$onMapToTheme,
37480
- _ref9$initialMethod = _ref9.initialMethod,
37481
- initialMethod = _ref9$initialMethod === void 0 ? null : _ref9$initialMethod;
37766
+ var ThemeQuickCreate = function ThemeQuickCreate(_ref0) {
37767
+ var wizardName = _ref0.wizardName,
37768
+ setWizardName = _ref0.setWizardName,
37769
+ wizardMethod = _ref0.wizardMethod,
37770
+ setWizardMethod = _ref0.setWizardMethod,
37771
+ wizardTheme = _ref0.wizardTheme,
37772
+ setWizardTheme = _ref0.setWizardTheme,
37773
+ onComplete = _ref0.onComplete,
37774
+ _ref0$onExtract = _ref0.onExtract,
37775
+ onExtract = _ref0$onExtract === void 0 ? null : _ref0$onExtract,
37776
+ _ref0$onMapToTheme = _ref0.onMapToTheme,
37777
+ onMapToTheme = _ref0$onMapToTheme === void 0 ? null : _ref0$onMapToTheme,
37778
+ _ref0$initialMethod = _ref0.initialMethod,
37779
+ initialMethod = _ref0$initialMethod === void 0 ? null : _ref0$initialMethod;
37482
37780
  var canCreate = wizardName.trim().length > 0 && wizardTheme !== null;
37483
37781
  var showMethodPicker = initialMethod === null;
37484
37782
  React.useEffect(function () {
@@ -66190,6 +66488,10 @@ function computeDashboardPreflight(_ref) {
66190
66488
 
66191
66489
  ComponentManager.registerContainerTypes(LayoutContainer, LayoutGridContainer);
66192
66490
 
66491
+ Object.defineProperty(exports, 'FontAwesomeIcon', {
66492
+ enumerable: true,
66493
+ get: function () { return DashReact.FontAwesomeIcon; }
66494
+ });
66193
66495
  Object.defineProperty(exports, 'ThemeContext', {
66194
66496
  enumerable: true,
66195
66497
  get: function () { return DashReact.ThemeContext; }