@trops/dash-core 0.1.604 → 0.1.605
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.esm.js +132 -12
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +132 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -2549,6 +2549,27 @@ var ThemeWrapper = function ThemeWrapper(_ref) {
|
|
|
2549
2549
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2550
2550
|
}, [chosenTheme, themeVariant, themeName, themesForApplication, rawThemes]);
|
|
2551
2551
|
|
|
2552
|
+
// Broadcast the app-level theme to a SEPARATE global so
|
|
2553
|
+
// components rendered OUTSIDE the React theme tree
|
|
2554
|
+
// (WidgetBuilderModal, AppUpdatesModal — they live as siblings
|
|
2555
|
+
// of DashboardStage in dash-electron's Dash.js render) can fall
|
|
2556
|
+
// back to it when no dashboard-specific override is in play.
|
|
2557
|
+
//
|
|
2558
|
+
// We can't share the same global with DashboardThemeProvider's
|
|
2559
|
+
// per-workspace broadcast because React commits child effects
|
|
2560
|
+
// BEFORE parent effects — ThemeWrapper would always run last
|
|
2561
|
+
// and silently overwrite the workspace theme. Two separate
|
|
2562
|
+
// globals avoid the race: consumers read
|
|
2563
|
+
// `__dashThemeContext` (workspace) first, fall back to
|
|
2564
|
+
// `__dashAppThemeContext` (app-level) when no workspace is open.
|
|
2565
|
+
useEffect(function () {
|
|
2566
|
+
if (typeof window === "undefined") return undefined;
|
|
2567
|
+
if (contextValue !== null && contextValue !== void 0 && contextValue.currentTheme) {
|
|
2568
|
+
window.__dashAppThemeContext = contextValue;
|
|
2569
|
+
window.dispatchEvent(new Event("dash:theme-changed"));
|
|
2570
|
+
}
|
|
2571
|
+
}, [contextValue]);
|
|
2572
|
+
|
|
2552
2573
|
// Write the active theme's CSS custom properties to :root so any
|
|
2553
2574
|
// hex-channel tokens (`bg-[var(--primary-700)]` etc. emitted by
|
|
2554
2575
|
// ThemeModel) resolve app-wide. Without this, saving a hex theme
|
|
@@ -5725,6 +5746,45 @@ function ThemeBroadcast(_ref) {
|
|
|
5725
5746
|
return null;
|
|
5726
5747
|
}
|
|
5727
5748
|
|
|
5749
|
+
/**
|
|
5750
|
+
* Writes the dashboard theme's cssVars to `:root` while mounted, and
|
|
5751
|
+
* restores the previous values on unmount / theme switch.
|
|
5752
|
+
*
|
|
5753
|
+
* ThemeWrapper writes the APP theme's cssVars at the top of the tree.
|
|
5754
|
+
* Without this helper, a dashboard that overrides the app theme with a
|
|
5755
|
+
* hex-channel theme (like "Slack Generic") would carry the right class
|
|
5756
|
+
* names (`bg-[var(--primary-900)]`) but the `--primary-900` variable
|
|
5757
|
+
* on :root would still be the APP theme's value — or undefined if the
|
|
5758
|
+
* app theme is named-family. Hex-themed surfaces then render with no
|
|
5759
|
+
* background. This effect closes that gap by promoting the dashboard
|
|
5760
|
+
* theme's cssVars to :root for the duration of its mount.
|
|
5761
|
+
*/
|
|
5762
|
+
function DashboardCssVarsBridge(_ref2) {
|
|
5763
|
+
var cssVars = _ref2.cssVars;
|
|
5764
|
+
useEffect(function () {
|
|
5765
|
+
if (!cssVars || typeof document === "undefined") return undefined;
|
|
5766
|
+
var root = document.documentElement;
|
|
5767
|
+
var previous = {};
|
|
5768
|
+
var keys = Object.keys(cssVars);
|
|
5769
|
+
for (var _i = 0, _keys = keys; _i < _keys.length; _i++) {
|
|
5770
|
+
var key = _keys[_i];
|
|
5771
|
+
previous[key] = root.style.getPropertyValue(key);
|
|
5772
|
+
root.style.setProperty(key, cssVars[key]);
|
|
5773
|
+
}
|
|
5774
|
+
return function () {
|
|
5775
|
+
for (var _i2 = 0, _keys2 = keys; _i2 < _keys2.length; _i2++) {
|
|
5776
|
+
var _key = _keys2[_i2];
|
|
5777
|
+
if (previous[_key]) {
|
|
5778
|
+
root.style.setProperty(_key, previous[_key]);
|
|
5779
|
+
} else {
|
|
5780
|
+
root.style.removeProperty(_key);
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
};
|
|
5784
|
+
}, [cssVars]);
|
|
5785
|
+
return null;
|
|
5786
|
+
}
|
|
5787
|
+
|
|
5728
5788
|
/**
|
|
5729
5789
|
* DashboardThemeProvider
|
|
5730
5790
|
*
|
|
@@ -5735,9 +5795,10 @@ function ThemeBroadcast(_ref) {
|
|
|
5735
5795
|
* App chrome (navbar, tab bar, sidebar) stays OUTSIDE this wrapper
|
|
5736
5796
|
* and keeps the app theme.
|
|
5737
5797
|
*/
|
|
5738
|
-
var DashboardThemeProvider = function DashboardThemeProvider(
|
|
5739
|
-
var
|
|
5740
|
-
|
|
5798
|
+
var DashboardThemeProvider = function DashboardThemeProvider(_ref3) {
|
|
5799
|
+
var _contextValue$current;
|
|
5800
|
+
var themeKey = _ref3.themeKey,
|
|
5801
|
+
children = _ref3.children;
|
|
5741
5802
|
var parentContext = useContext(ThemeContext);
|
|
5742
5803
|
var themes = parentContext.themes,
|
|
5743
5804
|
themeVariant = parentContext.themeVariant;
|
|
@@ -5769,6 +5830,8 @@ var DashboardThemeProvider = function DashboardThemeProvider(_ref2) {
|
|
|
5769
5830
|
value: contextValue,
|
|
5770
5831
|
children: [/*#__PURE__*/jsx(ThemeBroadcast, {
|
|
5771
5832
|
ctx: contextValue
|
|
5833
|
+
}), /*#__PURE__*/jsx(DashboardCssVarsBridge, {
|
|
5834
|
+
cssVars: contextValue === null || contextValue === void 0 || (_contextValue$current = contextValue.currentTheme) === null || _contextValue$current === void 0 ? void 0 : _contextValue$current.cssVars
|
|
5772
5835
|
}), children]
|
|
5773
5836
|
});
|
|
5774
5837
|
};
|
|
@@ -28958,6 +29021,36 @@ var WorkspaceModel = function WorkspaceModel(workspaceItem) {
|
|
|
28958
29021
|
function ownKeys$H(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
28959
29022
|
function _objectSpread$H(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$H(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$H(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
28960
29023
|
|
|
29024
|
+
/**
|
|
29025
|
+
* Last-resort family for ANY channel whose value can't be resolved
|
|
29026
|
+
* (unknown name, missing palette entry, missing shade, …). Picked
|
|
29027
|
+
* because it's universally safelist-covered, has every shade from
|
|
29028
|
+
* 50..950, and is visually neutral — so a misconfigured theme
|
|
29029
|
+
* renders "muted" rather than blank/transparent.
|
|
29030
|
+
*
|
|
29031
|
+
* Slack Generic etc. exposed this: when a channel value was missing
|
|
29032
|
+
* or unrecognized, ThemeModel silently emitted `bg-undefined-700`
|
|
29033
|
+
* (not in any safelist) → Tailwind dropped the class → the
|
|
29034
|
+
* dropdown popover rendered transparent. Falling back here means
|
|
29035
|
+
* no token can be "missing" by the time `getStylesForItem` reads it.
|
|
29036
|
+
*/
|
|
29037
|
+
var FALLBACK_FAMILY = "gray";
|
|
29038
|
+
|
|
29039
|
+
/**
|
|
29040
|
+
* Resolve a channel value to a safelist-covered Tailwind family
|
|
29041
|
+
* name. Returns the original value when it's a hex (the caller
|
|
29042
|
+
* handles those via CSS variables) or a recognized palette family;
|
|
29043
|
+
* otherwise returns FALLBACK_FAMILY so the resulting class always
|
|
29044
|
+
* renders.
|
|
29045
|
+
*/
|
|
29046
|
+
function resolveChannelFamily(channelValue) {
|
|
29047
|
+
if (isHexColor$1(channelValue)) return channelValue;
|
|
29048
|
+
if (typeof channelValue === "string" && channelValue.length > 0 && TAILWIND_PALETTE && TAILWIND_PALETTE[channelValue]) {
|
|
29049
|
+
return channelValue;
|
|
29050
|
+
}
|
|
29051
|
+
return FALLBACK_FAMILY;
|
|
29052
|
+
}
|
|
29053
|
+
|
|
28961
29054
|
/**
|
|
28962
29055
|
* getNextLevel
|
|
28963
29056
|
* Need to generate the levels for tailwind
|
|
@@ -28976,6 +29069,11 @@ function invert(shade) {
|
|
|
28976
29069
|
* shade. Routes to the arbitrary-value syntax (`bg-[var(--type-shade)]`)
|
|
28977
29070
|
* when the channel's value is a hex.
|
|
28978
29071
|
*
|
|
29072
|
+
* Layer 1 fallback (audit follow-up to the Slack Generic bug): if
|
|
29073
|
+
* `channelValue` isn't a hex AND isn't a recognized Tailwind palette
|
|
29074
|
+
* family, fall back to FALLBACK_FAMILY so the emitted class is
|
|
29075
|
+
* always safelist-covered and never resolves to `bg-undefined-700`.
|
|
29076
|
+
*
|
|
28979
29077
|
* @param {"bg"|"text"|"border"} prefix
|
|
28980
29078
|
* @param {string} type channel name (primary | secondary | …)
|
|
28981
29079
|
* @param {number} shade tailwind shade (100..950)
|
|
@@ -28985,10 +29083,11 @@ function invert(shade) {
|
|
|
28985
29083
|
function classFor(prefix, type, shade, channelValue) {
|
|
28986
29084
|
var hover = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
28987
29085
|
var h = hover ? "hover:" : "";
|
|
28988
|
-
|
|
29086
|
+
var resolved = resolveChannelFamily(channelValue);
|
|
29087
|
+
if (isHexColor$1(resolved)) {
|
|
28989
29088
|
return "".concat(h).concat(prefix, "-[var(--").concat(type, "-").concat(shade, ")]");
|
|
28990
29089
|
}
|
|
28991
|
-
return "".concat(h).concat(prefix, "-").concat(
|
|
29090
|
+
return "".concat(h).concat(prefix, "-").concat(resolved, "-").concat(shade);
|
|
28992
29091
|
}
|
|
28993
29092
|
|
|
28994
29093
|
/**
|
|
@@ -29001,8 +29100,10 @@ function classFor(prefix, type, shade, channelValue) {
|
|
|
29001
29100
|
* produce a `var(--{type}-{shade})` reference that resolves against
|
|
29002
29101
|
* the CSS custom properties ThemePreviewProvider writes to :root.
|
|
29003
29102
|
*
|
|
29004
|
-
*
|
|
29005
|
-
*
|
|
29103
|
+
* Layer 1 fallback: when the channel value or shade can't be
|
|
29104
|
+
* resolved, fall back to FALLBACK_FAMILY's shade so cssValue is
|
|
29105
|
+
* never null. Pairs with classFor's same fallback to guarantee
|
|
29106
|
+
* every (type, shade) tuple yields a renderable token.
|
|
29006
29107
|
*/
|
|
29007
29108
|
function cssValueFor(type, shade, channelValue) {
|
|
29008
29109
|
if (isHexColor$1(channelValue)) {
|
|
@@ -29015,12 +29116,17 @@ function cssValueFor(type, shade, channelValue) {
|
|
|
29015
29116
|
var _hex = shades[shade] || shades[String(shade)];
|
|
29016
29117
|
if (_hex) return _hex;
|
|
29017
29118
|
}
|
|
29018
|
-
return
|
|
29119
|
+
return fallbackCssValue(shade);
|
|
29019
29120
|
}
|
|
29020
29121
|
var family = TAILWIND_PALETTE && TAILWIND_PALETTE[channelValue];
|
|
29021
|
-
if (!family) return
|
|
29122
|
+
if (!family) return fallbackCssValue(shade);
|
|
29022
29123
|
var hex = family[shade] || family[String(shade)];
|
|
29023
|
-
return hex ||
|
|
29124
|
+
return hex || fallbackCssValue(shade);
|
|
29125
|
+
}
|
|
29126
|
+
function fallbackCssValue(shade) {
|
|
29127
|
+
var fallback = TAILWIND_PALETTE && TAILWIND_PALETTE[FALLBACK_FAMILY];
|
|
29128
|
+
if (!fallback) return null;
|
|
29129
|
+
return fallback[shade] || fallback[String(shade)] || null;
|
|
29024
29130
|
}
|
|
29025
29131
|
function gradientFor(direction, type, fromShade, viaShade, toShade, channelValue) {
|
|
29026
29132
|
if (isHexColor$1(channelValue)) {
|
|
@@ -35205,11 +35311,25 @@ var ChannelEditorModal = function ChannelEditorModal(_ref) {
|
|
|
35205
35311
|
var nearest = useMemo(function () {
|
|
35206
35312
|
return nearestSwatch(selectedHex, families);
|
|
35207
35313
|
}, [selectedHex, families]);
|
|
35314
|
+
|
|
35315
|
+
// Auto-switch the family tab when the underlying selected color
|
|
35316
|
+
// changes (user picked a different channel/shade or the theme
|
|
35317
|
+
// mutated). Track the last hex we synced for so we don't fight
|
|
35318
|
+
// the user's manual tab clicks — without this guard, every
|
|
35319
|
+
// re-render rebuilds `nearest` as a new object reference and the
|
|
35320
|
+
// effect snaps activeFamily back to the family containing the
|
|
35321
|
+
// current color, making it impossible to browse other families.
|
|
35322
|
+
var lastSyncedHexRef = useRef(null);
|
|
35208
35323
|
useEffect(function () {
|
|
35209
|
-
if (!isOpen)
|
|
35324
|
+
if (!isOpen) {
|
|
35325
|
+
lastSyncedHexRef.current = null;
|
|
35326
|
+
return;
|
|
35327
|
+
}
|
|
35328
|
+
if (lastSyncedHexRef.current === selectedHex) return;
|
|
35329
|
+
lastSyncedHexRef.current = selectedHex;
|
|
35210
35330
|
if (nearest) setActiveFamily(nearest.family);
|
|
35211
35331
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35212
|
-
}, [isOpen, nearest]);
|
|
35332
|
+
}, [isOpen, selectedHex, nearest]);
|
|
35213
35333
|
function expandChannel(channelKey) {
|
|
35214
35334
|
setActiveChannel(channelKey);
|
|
35215
35335
|
setActiveSlot("base");
|