dara-core 1.21.1__py3-none-any.whl → 1.21.2__py3-none-any.whl

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.
@@ -55,6 +55,7 @@ from dara.core.definitions import (
55
55
  )
56
56
  from dara.core.interactivity.actions import ActionImpl, ResetVariables
57
57
  from dara.core.interactivity.any_variable import AnyVariable
58
+ from dara.core.interactivity.client_variable import ClientVariable
58
59
  from dara.core.internal.encoder_registry import Encoder
59
60
  from dara.core.internal.import_discovery import (
60
61
  create_action_definition,
@@ -525,14 +526,14 @@ class ConfigurationBuilder:
525
526
 
526
527
  def set_theme(
527
528
  self,
528
- main_theme: Optional[Union[ThemeDef, Literal['light'], Literal['dark']]] = None,
529
+ main_theme: Optional[Union[ThemeDef, ClientVariable, Literal['light'], Literal['dark']]] = None,
529
530
  base_theme: Optional[Union[Literal['light'], Literal['dark']]] = None,
530
531
  ):
531
532
  """
532
533
  Sets the color theme of the app. Takes ThemeDef models for the app, and reverts
533
534
  to the default themes if they are not supplied.
534
535
 
535
- :param main_theme: ThemeDef defining colors for the app, alternatively can be either 'light' or 'dark' to use default Dara colors
536
+ :param main_theme: ThemeDef defining colors for the app, a string 'light' or 'dark' to use default Dara colors, or a Variable containing one of the before
536
537
  """
537
538
  if isinstance(main_theme, str):
538
539
  if main_theme in ('dark', 'light'):
dara/core/defaults.py CHANGED
@@ -53,6 +53,8 @@ from dara.core.visual.components import (
53
53
  RowFallbackDef,
54
54
  SideBarFrame,
55
55
  SideBarFrameDef,
56
+ ThemeProvider,
57
+ ThemeProviderDef,
56
58
  TopBarFrame,
57
59
  TopBarFrameDef,
58
60
  )
@@ -89,6 +91,7 @@ CORE_COMPONENTS: Dict[str, ComponentTypeAnnotation] = {
89
91
  Link.__name__: LinkDef,
90
92
  Outlet.__name__: OutletDef,
91
93
  PoweredByCausalens.__name__: PoweredByCausalensDef,
94
+ ThemeProvider.__name__: ThemeProviderDef,
92
95
  }
93
96
 
94
97
  # These actions are provided by the core JS of this module
dara/core/main.py CHANGED
@@ -402,7 +402,6 @@ def _start_application(config: Configuration):
402
402
  'application_name': get_settings().project_name,
403
403
  'enable_devtools': config.enable_devtools,
404
404
  'live_reload': config.live_reload,
405
- # TODO: this will become some backendstore-variable instead, prepopulated in here
406
405
  'theme': config.theme,
407
406
  'title': config.title,
408
407
  'context_components': config.context_components,
@@ -5467,6 +5467,75 @@
5467
5467
  var Recoil_index_28 = Recoil_index.useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE;
5468
5468
  var Recoil_index_31 = Recoil_index.useRecoilCallback;
5469
5469
  var Recoil_index_34 = Recoil_index.useRecoilSnapshot;
5470
+ var Key;
5471
+ (function(Key2) {
5472
+ Key2["BACKSPACE"] = "Backspace";
5473
+ Key2["CTRL"] = "Control";
5474
+ Key2["DOWN"] = "ArrowDown";
5475
+ Key2["ENTER"] = "Enter";
5476
+ Key2["ESCAPE"] = "Escape";
5477
+ Key2["LEFT"] = "ArrowLeft";
5478
+ Key2["META"] = "Meta";
5479
+ Key2["MINUS"] = "-";
5480
+ Key2["PERIOD"] = ".";
5481
+ Key2["RIGHT"] = "ArrowRight";
5482
+ Key2["SHIFT"] = "Shift";
5483
+ Key2["TAB"] = "Tab";
5484
+ Key2["UP"] = "ArrowUp";
5485
+ })(Key || (Key = {}));
5486
+ const CONTROL_KEYS = [
5487
+ Key.ESCAPE,
5488
+ Key.TAB,
5489
+ Key.ENTER,
5490
+ Key.BACKSPACE,
5491
+ Key.CTRL,
5492
+ Key.SHIFT,
5493
+ Key.UP,
5494
+ Key.DOWN,
5495
+ Key.LEFT,
5496
+ Key.RIGHT,
5497
+ Key.META
5498
+ ];
5499
+ var jsxRuntime = { exports: {} };
5500
+ var reactJsxRuntime_production_min = {};
5501
+ /**
5502
+ * @license React
5503
+ * react-jsx-runtime.production.min.js
5504
+ *
5505
+ * Copyright (c) Facebook, Inc. and its affiliates.
5506
+ *
5507
+ * This source code is licensed under the MIT license found in the
5508
+ * LICENSE file in the root directory of this source tree.
5509
+ */
5510
+ var hasRequiredReactJsxRuntime_production_min;
5511
+ function requireReactJsxRuntime_production_min() {
5512
+ if (hasRequiredReactJsxRuntime_production_min) return reactJsxRuntime_production_min;
5513
+ hasRequiredReactJsxRuntime_production_min = 1;
5514
+ var f = React$1, k = Symbol.for("react.element"), l2 = Symbol.for("react.fragment"), m = Object.prototype.hasOwnProperty, n2 = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p2 = { key: true, ref: true, __self: true, __source: true };
5515
+ function q(c, a2, g) {
5516
+ var b2, d2 = {}, e2 = null, h = null;
5517
+ void 0 !== g && (e2 = "" + g);
5518
+ void 0 !== a2.key && (e2 = "" + a2.key);
5519
+ void 0 !== a2.ref && (h = a2.ref);
5520
+ for (b2 in a2) m.call(a2, b2) && !p2.hasOwnProperty(b2) && (d2[b2] = a2[b2]);
5521
+ if (c && c.defaultProps) for (b2 in a2 = c.defaultProps, a2) void 0 === d2[b2] && (d2[b2] = a2[b2]);
5522
+ return { $$typeof: k, type: c, key: e2, ref: h, props: d2, _owner: n2.current };
5523
+ }
5524
+ reactJsxRuntime_production_min.Fragment = l2;
5525
+ reactJsxRuntime_production_min.jsx = q;
5526
+ reactJsxRuntime_production_min.jsxs = q;
5527
+ return reactJsxRuntime_production_min;
5528
+ }
5529
+ var hasRequiredJsxRuntime;
5530
+ function requireJsxRuntime() {
5531
+ if (hasRequiredJsxRuntime) return jsxRuntime.exports;
5532
+ hasRequiredJsxRuntime = 1;
5533
+ {
5534
+ jsxRuntime.exports = requireReactJsxRuntime_production_min();
5535
+ }
5536
+ return jsxRuntime.exports;
5537
+ }
5538
+ var jsxRuntimeExports = requireJsxRuntime();
5470
5539
  const theme = {
5471
5540
  colors: {
5472
5541
  primary: "#3796F6",
@@ -5566,75 +5635,6 @@
5566
5635
  function useClTheme() {
5567
5636
  return styled.useTheme();
5568
5637
  }
5569
- var Key;
5570
- (function(Key2) {
5571
- Key2["BACKSPACE"] = "Backspace";
5572
- Key2["CTRL"] = "Control";
5573
- Key2["DOWN"] = "ArrowDown";
5574
- Key2["ENTER"] = "Enter";
5575
- Key2["ESCAPE"] = "Escape";
5576
- Key2["LEFT"] = "ArrowLeft";
5577
- Key2["META"] = "Meta";
5578
- Key2["MINUS"] = "-";
5579
- Key2["PERIOD"] = ".";
5580
- Key2["RIGHT"] = "ArrowRight";
5581
- Key2["SHIFT"] = "Shift";
5582
- Key2["TAB"] = "Tab";
5583
- Key2["UP"] = "ArrowUp";
5584
- })(Key || (Key = {}));
5585
- const CONTROL_KEYS = [
5586
- Key.ESCAPE,
5587
- Key.TAB,
5588
- Key.ENTER,
5589
- Key.BACKSPACE,
5590
- Key.CTRL,
5591
- Key.SHIFT,
5592
- Key.UP,
5593
- Key.DOWN,
5594
- Key.LEFT,
5595
- Key.RIGHT,
5596
- Key.META
5597
- ];
5598
- var jsxRuntime = { exports: {} };
5599
- var reactJsxRuntime_production_min = {};
5600
- /**
5601
- * @license React
5602
- * react-jsx-runtime.production.min.js
5603
- *
5604
- * Copyright (c) Facebook, Inc. and its affiliates.
5605
- *
5606
- * This source code is licensed under the MIT license found in the
5607
- * LICENSE file in the root directory of this source tree.
5608
- */
5609
- var hasRequiredReactJsxRuntime_production_min;
5610
- function requireReactJsxRuntime_production_min() {
5611
- if (hasRequiredReactJsxRuntime_production_min) return reactJsxRuntime_production_min;
5612
- hasRequiredReactJsxRuntime_production_min = 1;
5613
- var f = React$1, k = Symbol.for("react.element"), l2 = Symbol.for("react.fragment"), m = Object.prototype.hasOwnProperty, n2 = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p2 = { key: true, ref: true, __self: true, __source: true };
5614
- function q(c, a2, g) {
5615
- var b2, d2 = {}, e2 = null, h = null;
5616
- void 0 !== g && (e2 = "" + g);
5617
- void 0 !== a2.key && (e2 = "" + a2.key);
5618
- void 0 !== a2.ref && (h = a2.ref);
5619
- for (b2 in a2) m.call(a2, b2) && !p2.hasOwnProperty(b2) && (d2[b2] = a2[b2]);
5620
- if (c && c.defaultProps) for (b2 in a2 = c.defaultProps, a2) void 0 === d2[b2] && (d2[b2] = a2[b2]);
5621
- return { $$typeof: k, type: c, key: e2, ref: h, props: d2, _owner: n2.current };
5622
- }
5623
- reactJsxRuntime_production_min.Fragment = l2;
5624
- reactJsxRuntime_production_min.jsx = q;
5625
- reactJsxRuntime_production_min.jsxs = q;
5626
- return reactJsxRuntime_production_min;
5627
- }
5628
- var hasRequiredJsxRuntime;
5629
- function requireJsxRuntime() {
5630
- if (hasRequiredJsxRuntime) return jsxRuntime.exports;
5631
- hasRequiredJsxRuntime = 1;
5632
- {
5633
- jsxRuntime.exports = requireReactJsxRuntime_production_min();
5634
- }
5635
- return jsxRuntime.exports;
5636
- }
5637
- var jsxRuntimeExports = requireJsxRuntime();
5638
5638
  var Collapse = {};
5639
5639
  var hasRequiredCollapse;
5640
5640
  function requireCollapse() {
@@ -73991,6 +73991,20 @@ Inferred class string: "${iconClasses}."`
73991
73991
  }
73992
73992
  return PRELOADED_COMPONENTS[identifier];
73993
73993
  }
73994
+ const GlobalStyle = styled.createGlobalStyle`
73995
+ /* stylelint-disable selector-id-pattern */
73996
+ html,
73997
+ body,
73998
+ #dara_root {
73999
+ font-size: ${(props) => props.theme.font.size};
74000
+ }
74001
+ `;
74002
+ function StyleRoot(props) {
74003
+ const config2 = useConfig();
74004
+ const [mainTheme] = useVariable(config2.theme.main);
74005
+ const theme2 = React$1.useMemo(() => resolveTheme(mainTheme, config2.theme.base), [config2.theme.base, mainTheme]);
74006
+ return /* @__PURE__ */ React.createElement(styled.ThemeProvider, { theme: theme2 }, /* @__PURE__ */ React.createElement(GlobalStyle, null), props.children);
74007
+ }
73994
74008
  function UnauthenticatedRoot() {
73995
74009
  const syncOptions = useUrlSync();
73996
74010
  const navigation = useNavigation();
@@ -74012,7 +74026,7 @@ Inferred class string: "${iconClasses}."`
74012
74026
  }
74013
74027
  }
74014
74028
  }, [navigation.state]);
74015
- return /* @__PURE__ */ React.createElement(PathParamSync, null, /* @__PURE__ */ React.createElement(RecoilSync_index_3, { ...syncOptions }, /* @__PURE__ */ React.createElement(Outlet, null)));
74029
+ return /* @__PURE__ */ React.createElement(PathParamSync, null, /* @__PURE__ */ React.createElement(RecoilSync_index_3, { ...syncOptions }, /* @__PURE__ */ React.createElement(StyleRoot, null, /* @__PURE__ */ React.createElement(Outlet, null))));
74016
74030
  }
74017
74031
  class SingleUseCache {
74018
74032
  constructor(options = {}) {
@@ -74534,7 +74548,7 @@ Inferred class string: "${iconClasses}."`
74534
74548
  );
74535
74549
  }
74536
74550
  function Root(props) {
74537
- return /* @__PURE__ */ React.createElement(ConfigContextProvider, { initialConfig: props.daraData }, /* @__PURE__ */ React.createElement(reactQuery.QueryClientProvider, { client: props.queryClient }, /* @__PURE__ */ React.createElement(styled.ThemeProvider, { theme: props.theme }, /* @__PURE__ */ React.createElement(ErrorBoundary$1, null, /* @__PURE__ */ React.createElement(importersCtx.Provider, { value: props.importers }, /* @__PURE__ */ React.createElement(directionCtx.Provider, { value: { direction: "row" } }, /* @__PURE__ */ React.createElement(Recoil_index_5, null, /* @__PURE__ */ React.createElement(GlobalTaskProvider, null, /* @__PURE__ */ React.createElement(RouterRoot, { daraData: props.daraData })))))))));
74551
+ return /* @__PURE__ */ React.createElement(ConfigContextProvider, { initialConfig: props.daraData }, /* @__PURE__ */ React.createElement(reactQuery.QueryClientProvider, { client: props.queryClient }, /* @__PURE__ */ React.createElement(ErrorBoundary$1, null, /* @__PURE__ */ React.createElement(importersCtx.Provider, { value: props.importers }, /* @__PURE__ */ React.createElement(directionCtx.Provider, { value: { direction: "row" } }, /* @__PURE__ */ React.createElement(Recoil_index_5, null, /* @__PURE__ */ React.createElement(GlobalTaskProvider, null, /* @__PURE__ */ React.createElement(RouterRoot, { daraData: props.daraData }))))))));
74538
74552
  }
74539
74553
  async function run(importers) {
74540
74554
  const queryClient = new reactQuery.QueryClient();
@@ -74549,10 +74563,9 @@ Inferred class string: "${iconClasses}."`
74549
74563
  preloadComponents(importers, Object.values(daraData.components)),
74550
74564
  preloadActions(importers, Object.values(daraData.actions))
74551
74565
  ]);
74552
- const theme2 = resolveTheme(daraData.theme?.main, daraData.theme?.base);
74553
74566
  const container = document.getElementById("dara_root");
74554
74567
  const root = clientExports.createRoot(container);
74555
- root.render(/* @__PURE__ */ React.createElement(Root, { daraData, queryClient, importers, theme: theme2 }));
74568
+ root.render(/* @__PURE__ */ React.createElement(Root, { daraData, queryClient, importers }));
74556
74569
  }
74557
74570
  function isValidHttpUrl(url) {
74558
74571
  if (url.startsWith("/")) {
@@ -98283,7 +98296,7 @@ Inferred class string: "${iconClasses}."`
98283
98296
  const logoSrc = theme2.themeType === "dark" ? DaraDark : DaraLight;
98284
98297
  const daraLogo = /* @__PURE__ */ React.createElement("img", { alt: "Dara Logo", src: logoSrc });
98285
98298
  const showPoweredBy = props.powered_by_causalens ?? config2.powered_by_causalens;
98286
- return /* @__PURE__ */ React.createElement(Wrapper, { backgroundColor: theme2.colors.background }, props.side_bar_position === "right" && /* @__PURE__ */ React.createElement(Wrapper, null, props.content && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.content })), /* @__PURE__ */ React.createElement(styled.ThemeContext.Provider, { value: resolveTheme(config2.theme?.main, config2.theme?.base) }, /* @__PURE__ */ React.createElement(SideBar, { style: { padding: props.side_bar_padding }, width: props.side_bar_width }, !props.hide_logo && props.logo_position !== "bottom" && logo, /* @__PURE__ */ React.createElement(Wrapper, { direction: "column" }, /* @__PURE__ */ React.createElement(directionCtx.Provider, { value: { direction: "column" } }, props.side_bar && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.side_bar }))), !props.hide_logo && props.logo_position === "bottom" && logo, /* @__PURE__ */ React.createElement(LogoutButton$1, { href: "/logout", styling: "error" }, /* @__PURE__ */ React.createElement(LogoutArrow$1, { style: { marginRight: "0.5rem" } }), "Logout"), /* @__PURE__ */ React.createElement(BuiltWithLink, { href: "https://github.com/causalens/dara", target: "_blank", rel: "noopener noreferrer" }, "Built with ", daraLogo), showPoweredBy && /* @__PURE__ */ React.createElement(PoweredByCausalens, null))), props.side_bar_position !== "right" && /* @__PURE__ */ React.createElement(Wrapper, { style: { padding: "2rem 3rem" } }, props.content && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.content })));
98299
+ return /* @__PURE__ */ React.createElement(Wrapper, { backgroundColor: theme2.colors.background }, props.side_bar_position === "right" && /* @__PURE__ */ React.createElement(Wrapper, null, props.content && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.content })), /* @__PURE__ */ React.createElement(SideBar, { style: { padding: props.side_bar_padding }, width: props.side_bar_width }, !props.hide_logo && props.logo_position !== "bottom" && logo, /* @__PURE__ */ React.createElement(Wrapper, { direction: "column" }, /* @__PURE__ */ React.createElement(directionCtx.Provider, { value: { direction: "column" } }, props.side_bar && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.side_bar }))), !props.hide_logo && props.logo_position === "bottom" && logo, /* @__PURE__ */ React.createElement(LogoutButton$1, { href: "/logout", styling: "error" }, /* @__PURE__ */ React.createElement(LogoutArrow$1, { style: { marginRight: "0.5rem" } }), "Logout"), /* @__PURE__ */ React.createElement(BuiltWithLink, { href: "https://github.com/causalens/dara", target: "_blank", rel: "noopener noreferrer" }, "Built with ", daraLogo), showPoweredBy && /* @__PURE__ */ React.createElement(PoweredByCausalens, null)), props.side_bar_position !== "right" && /* @__PURE__ */ React.createElement(Wrapper, { style: { padding: "2rem 3rem" } }, props.content && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.content })));
98287
98300
  }
98288
98301
  const shouldForwardProp = (prop) => !["width"].includes(prop);
98289
98302
  const TopBar = styled.div.withConfig({ shouldForwardProp })`
@@ -98362,11 +98375,10 @@ Inferred class string: "${iconClasses}."`
98362
98375
  const LogoutArrow = getIcon("fa-solid fa-arrow-right-from-bracket");
98363
98376
  function TopBarFrame(props) {
98364
98377
  const theme2 = useClTheme();
98365
- const config2 = useConfig();
98366
98378
  const logo = props.logo_path && /* @__PURE__ */ React.createElement(LogoImage, { alt: "Logo", src: prependBaseUrl(props.logo_path), width: props.logo_width });
98367
98379
  const logoSrc = theme2.themeType === "dark" ? DaraDark : DaraLight;
98368
98380
  const daraLogo = /* @__PURE__ */ React.createElement("img", { alt: "Dara", src: logoSrc });
98369
- return /* @__PURE__ */ React.createElement(Wrapper, { backgroundColor: theme2.colors.background, direction: "column" }, /* @__PURE__ */ React.createElement(styled.ThemeContext.Provider, { value: resolveTheme(config2?.theme?.main, config2?.theme?.base) }, /* @__PURE__ */ React.createElement(TopBar, { height: props.top_bar_height, style: { padding: props.top_bar_padding } }, /* @__PURE__ */ React.createElement(TopBarContent, null, !props.hide_logo && logo, props.top_bar && /* @__PURE__ */ React.createElement(RouteButtons, { direction: "row" }, /* @__PURE__ */ React.createElement(directionCtx.Provider, { value: { direction: "row" } }, props.top_bar && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.top_bar }))), /* @__PURE__ */ React.createElement(LogoutButton, { href: "/logout", styling: "error" }, /* @__PURE__ */ React.createElement(LogoutArrow, { style: { marginRight: "0.5rem" } }), "Logout")), /* @__PURE__ */ React.createElement(BuiltWithSpan, null, "Built with ", daraLogo))), /* @__PURE__ */ React.createElement(Wrapper, { style: { padding: "2rem 3rem" } }, props.content && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.content })));
98381
+ return /* @__PURE__ */ React.createElement(Wrapper, { backgroundColor: theme2.colors.background, direction: "column" }, /* @__PURE__ */ React.createElement(TopBar, { height: props.top_bar_height, style: { padding: props.top_bar_padding } }, /* @__PURE__ */ React.createElement(TopBarContent, null, !props.hide_logo && logo, props.top_bar && /* @__PURE__ */ React.createElement(RouteButtons, { direction: "row" }, /* @__PURE__ */ React.createElement(directionCtx.Provider, { value: { direction: "row" } }, props.top_bar && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.top_bar }))), /* @__PURE__ */ React.createElement(LogoutButton, { href: "/logout", styling: "error" }, /* @__PURE__ */ React.createElement(LogoutArrow, { style: { marginRight: "0.5rem" } }), "Logout")), /* @__PURE__ */ React.createElement(BuiltWithSpan, null, "Built with ", daraLogo)), /* @__PURE__ */ React.createElement(Wrapper, { style: { padding: "2rem 3rem" } }, props.content && /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: props.content })));
98370
98382
  }
98371
98383
  const RowDots = styled(Dots)`
98372
98384
  height: 2.5rem;
@@ -98452,6 +98464,16 @@ Inferred class string: "${iconClasses}."`
98452
98464
  const { suspend } = useFallbackCtx();
98453
98465
  return /* @__PURE__ */ React__namespace.createElement(fallbackCtx.Provider, { value: { suspend: false } }, /* @__PURE__ */ React__namespace.createElement(ForImpl, { ...props, suspend }));
98454
98466
  }
98467
+ const StyledDiv = injectCss(styled.div`
98468
+ /* empty */
98469
+ `);
98470
+ function ThemeProvider(props) {
98471
+ const [style, css2] = useComponentStyles(props);
98472
+ const [mainTheme] = useVariable(props.theme);
98473
+ const [baseTheme] = useVariable(props.base_theme);
98474
+ const theme2 = React$1.useMemo(() => resolveTheme(mainTheme, baseTheme), [baseTheme, mainTheme]);
98475
+ return /* @__PURE__ */ React.createElement(styled.ThemeProvider, { theme: theme2 }, /* @__PURE__ */ React.createElement(StyledDiv, { style: { fontSize: theme2.font.size, ...style }, $rawCss: css2 }, props.children.map((c) => /* @__PURE__ */ React.createElement(DynamicComponent$1, { component: c, key: c.uid }))));
98476
+ }
98455
98477
  exports.ActionImpl = ActionImpl;
98456
98478
  exports.AuthType = AuthType;
98457
98479
  exports.AuthenticatedRoot = TemplateRoot;
@@ -98495,6 +98517,7 @@ Inferred class string: "${iconClasses}."`
98495
98517
  exports.RowFallback = RowFallback;
98496
98518
  exports.ServerVariableSyncProvider = ServerVariableSyncProvider;
98497
98519
  exports.SideBarFrame = SideBarFrame;
98520
+ exports.ThemeProvider = ThemeProvider;
98498
98521
  exports.TopBarFrame = TopBarFrame;
98499
98522
  exports.TriggerVariable = TriggerVariable;
98500
98523
  exports.UpdateVariable = UpdateVariable;
dara/core/umd/style.css CHANGED
@@ -743,6 +743,11 @@
743
743
  .react-datepicker__portal .react-datepicker-time__header {
744
744
  font-size: 1.44rem;
745
745
  }
746
+ /*
747
+ * This file only contains styles independent of the theme,
748
+ * mostly a css reset. Theme-specific styles are created using createGlobalStyle.
749
+ */
750
+
746
751
  @font-face {
747
752
  font-family: 'Manrope';
748
753
  font-weight: 300 900;
@@ -759,7 +764,6 @@ body,
759
764
  width: 100%;
760
765
 
761
766
  font-family: 'Manrope';
762
- font-size: 16px;
763
767
  }
764
768
 
765
769
  /* The following is a css-reset from: https://piccalil.li/blog/a-modern-css-reset */
@@ -839,13 +843,12 @@ select {
839
843
  }
840
844
  }
841
845
 
846
+ /* NOTE: the nprogress color is hard-coded intentionally as we want a blue progress bar regardless of the theme */
842
847
  #nprogress {
843
848
  pointer-events: none;
844
849
  }
845
850
 
846
851
  #nprogress .bar {
847
- background: #3796f6;
848
-
849
852
  position: fixed;
850
853
  z-index: 1031;
851
854
  top: 0;
@@ -853,27 +856,29 @@ select {
853
856
 
854
857
  width: 100%;
855
858
  height: 2px;
859
+
860
+ background: #3796f6;
856
861
  }
857
862
 
858
863
  #nprogress .peg {
859
- display: block;
860
864
  position: absolute;
861
- right: 0px;
865
+ right: 0;
866
+ transform: rotate(3deg) translate(0, -4px);
867
+
868
+ display: block;
869
+
862
870
  width: 100px;
863
871
  height: 100%;
872
+
873
+ opacity: 1;
864
874
  box-shadow:
865
875
  0 0 10px #3796f6,
866
876
  0 0 5px #3796f6;
867
- opacity: 1;
868
-
869
- -webkit-transform: rotate(3deg) translate(0px, -4px);
870
- -ms-transform: rotate(3deg) translate(0px, -4px);
871
- transform: rotate(3deg) translate(0px, -4px);
872
877
  }
873
878
 
874
879
  .nprogress-custom-parent {
875
- overflow: hidden;
876
880
  position: relative;
881
+ overflow: hidden;
877
882
  }
878
883
 
879
884
  .nprogress-custom-parent #nprogress .spinner,
@@ -43,6 +43,7 @@ from .progress_tracker import (
43
43
  from .raw_string import RawString
44
44
  from .router_content import RouterContent, RouterContentDef
45
45
  from .sidebar_frame import SideBarFrame, SideBarFrameDef
46
+ from .theme_provider import ThemeProvider, ThemeProviderDef
46
47
  from .topbar_frame import TopBarFrame, TopBarFrameDef
47
48
 
48
49
  __all__ = [
@@ -67,6 +68,8 @@ __all__ = [
67
68
  'Fallback',
68
69
  'PoweredByCausalens',
69
70
  'PoweredByCausalensDef',
71
+ 'ThemeProvider',
72
+ 'ThemeProviderDef',
70
73
  ]
71
74
 
72
75
  for symbol in list(globals().values()) + [Fallback.Default, Fallback.Row]:
@@ -0,0 +1,44 @@
1
+ from typing import Literal, Union
2
+
3
+ from dara.core.definitions import ComponentInstance, JsComponentDef, StyledComponentInstance
4
+ from dara.core.interactivity.client_variable import ClientVariable
5
+ from dara.core.visual.themes.definitions import ThemeDef
6
+
7
+ ThemeProviderDef = JsComponentDef(name='ThemeProvider', js_module='@darajs/core', py_module='dara.core')
8
+
9
+
10
+ class ThemeProvider(StyledComponentInstance):
11
+ """
12
+ ThemeProvider can be used to provide a different theme to a subtree of components.
13
+
14
+ ```python
15
+ from dara.core import ConfigurationBuilder
16
+ from dara.core.visual.components import ThemeProvider
17
+ from dara.core.visual.themes import Light
18
+
19
+ config = ConfigurationBuilder()
20
+
21
+ # Define a theme by cloning Light and modifying it
22
+ theme = Light.model_copy()
23
+ theme.colors.text = 'red'
24
+
25
+ def ThemePage():
26
+ return Stack(
27
+ Text('This text is default color'),
28
+ ThemeProvider(
29
+ Text('This text is red'),
30
+ theme=theme
31
+ )
32
+ )
33
+
34
+ config.router.add_page(path='theme', content=ThemePage)
35
+ """
36
+
37
+ theme: Union[ThemeDef, ClientVariable, Literal['light', 'dark']]
38
+ base: Union[ClientVariable, Literal['light', 'dark']] = 'light'
39
+
40
+ def __init__(self, *children: ComponentInstance, **kwargs):
41
+ components = list(children)
42
+ if 'children' not in kwargs:
43
+ kwargs['children'] = components
44
+ super().__init__(**kwargs)
@@ -18,6 +18,7 @@ limitations under the License.
18
18
  from typing import Literal, Optional, Union
19
19
 
20
20
  from dara.core.base_definitions import DaraBaseModel as BaseModel
21
+ from dara.core.interactivity.client_variable import ClientVariable
21
22
 
22
23
 
23
24
  class ThemeColors(BaseModel):
@@ -96,5 +97,5 @@ class BaseTheme(BaseModel):
96
97
  Defines the base theming scheme of an app
97
98
  """
98
99
 
99
- main: Union[ThemeDef, Literal['light'], Literal['dark']]
100
+ main: Union[ThemeDef, ClientVariable, Literal['light'], Literal['dark']]
100
101
  base: Optional[Union[Literal['light'], Literal['dark']]] = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dara-core
3
- Version: 1.21.1
3
+ Version: 1.21.2
4
4
  Summary: Dara Framework Core
5
5
  Home-page: https://dara.causalens.com/
6
6
  License: Apache-2.0
@@ -21,10 +21,10 @@ Requires-Dist: cachetools (>=5.0.0,<6.0.0)
21
21
  Requires-Dist: certifi (>=2024.7.4)
22
22
  Requires-Dist: click (==8.1.3)
23
23
  Requires-Dist: colorama (>=0.4.6,<0.5.0)
24
- Requires-Dist: create-dara-app (==1.21.1)
24
+ Requires-Dist: create-dara-app (==1.21.2)
25
25
  Requires-Dist: croniter (>=1.0.15,<3.0.0)
26
26
  Requires-Dist: cryptography (>=42.0.4)
27
- Requires-Dist: dara-components (==1.21.1) ; extra == "all"
27
+ Requires-Dist: dara-components (==1.21.2) ; extra == "all"
28
28
  Requires-Dist: exceptiongroup (>=1.1.3,<2.0.0)
29
29
  Requires-Dist: fastapi (>=0.115.0,<0.116.0)
30
30
  Requires-Dist: fastapi_vite_dara (==0.4.0)
@@ -55,7 +55,7 @@ Description-Content-Type: text/markdown
55
55
 
56
56
  # Dara Application Framework
57
57
 
58
- <img src="https://github.com/causalens/dara/blob/v1.21.1/img/dara_light.svg?raw=true">
58
+ <img src="https://github.com/causalens/dara/blob/v1.21.2/img/dara_light.svg?raw=true">
59
59
 
60
60
  ![Master tests](https://github.com/causalens/dara/actions/workflows/tests.yml/badge.svg?branch=master)
61
61
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
@@ -100,7 +100,7 @@ source .venv/bin/activate
100
100
  dara start
101
101
  ```
102
102
 
103
- ![Dara App](https://github.com/causalens/dara/blob/v1.21.1/img/components_gallery.png?raw=true)
103
+ ![Dara App](https://github.com/causalens/dara/blob/v1.21.2/img/components_gallery.png?raw=true)
104
104
 
105
105
  Note: `pip` installation uses [PEP 660](https://peps.python.org/pep-0660/) `pyproject.toml`-based editable installs which require `pip >= 21.3` and `setuptools >= 64.0.0`. You can upgrade both with:
106
106
 
@@ -117,9 +117,9 @@ Explore some of our favorite apps - a great way of getting started and getting t
117
117
 
118
118
  | Dara App | Description |
119
119
  | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
120
- | ![Large Language Model](https://github.com/causalens/dara/blob/v1.21.1/img/llm.png?raw=true) | Demonstrates how to use incorporate a LLM chat box into your decision app to understand model insights |
121
- | ![Plot Interactivity](https://github.com/causalens/dara/blob/v1.21.1/img/plot_interactivity.png?raw=true) | Demonstrates how to enable the user to interact with plots, trigger actions based on clicks, mouse movements and other interactions with `Bokeh` or `Plotly` plots |
122
- | ![Graph Editor](https://github.com/causalens/dara/blob/v1.21.1/img/graph_viewer.png?raw=true) | Demonstrates how to use the `CausalGraphViewer` component to display your graphs or networks, customising the displayed information through colors and tooltips, and updating the page based on user interaction. |
120
+ | ![Large Language Model](https://github.com/causalens/dara/blob/v1.21.2/img/llm.png?raw=true) | Demonstrates how to use incorporate a LLM chat box into your decision app to understand model insights |
121
+ | ![Plot Interactivity](https://github.com/causalens/dara/blob/v1.21.2/img/plot_interactivity.png?raw=true) | Demonstrates how to enable the user to interact with plots, trigger actions based on clicks, mouse movements and other interactions with `Bokeh` or `Plotly` plots |
122
+ | ![Graph Editor](https://github.com/causalens/dara/blob/v1.21.2/img/graph_viewer.png?raw=true) | Demonstrates how to use the `CausalGraphViewer` component to display your graphs or networks, customising the displayed information through colors and tooltips, and updating the page based on user interaction. |
123
123
 
124
124
  Check out our [App Gallery](https://dara.causalens.com/gallery) for more inspiration!
125
125
 
@@ -146,9 +146,9 @@ And the supporting UI packages and tools.
146
146
  - `ui-utils` - miscellaneous utility functions
147
147
  - `ui-widgets` - widget components
148
148
 
149
- More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.21.1/CONTRIBUTING.md) file.
149
+ More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.21.2/CONTRIBUTING.md) file.
150
150
 
151
151
  ## License
152
152
 
153
- Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.21.1/LICENSE).
153
+ Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.21.2/LICENSE).
154
154
 
@@ -8,10 +8,10 @@ dara/core/auth/routes.py,sha256=0o5KXApRbkL0F5qFsarQk_cq5lbQ3QfIHR_mwLRgBEY,7217
8
8
  dara/core/auth/utils.py,sha256=iEWP5qwfH17Mi-5t3sP-DNMUrWN0oSRk96NhieY2Zw4,7334
9
9
  dara/core/base_definitions.py,sha256=ptc6OSx-qElWWSuZB4-06kWmnj6hekpKR47eeB36igQ,16915
10
10
  dara/core/cli.py,sha256=V__LAK3ozWGsVTEQHqvJwqSfpC3o6R76YGABJ-YVoSE,8185
11
- dara/core/configuration.py,sha256=8gp2rsQBAigv6GD69Op0_xyW7d5WZEI3CcUYXgp7LTY,23381
11
+ dara/core/configuration.py,sha256=caPebHNUmYqh9czEBwQiIDjGrH8ltsphayZICj1CRhc,23489
12
12
  dara/core/css.py,sha256=UkNZ6n7RDBLsHmpZvn_a3K2nAwxVggQJbQMKNbgXONA,1753
13
13
  dara/core/data_utils.py,sha256=RD5_GdyGyGr1LVThCo8mpuOMWrd9_c1iyRqjuyoarXM,12578
14
- dara/core/defaults.py,sha256=yZbioRVDMZU8nw99jryKaazAi46Z2GAZw_gl9CNTOQQ,4594
14
+ dara/core/defaults.py,sha256=J1-IX4nKcE6kXzqx7kq1ereU4MKXiMitZxSZo2rs7-U,4681
15
15
  dara/core/definitions.py,sha256=I4TUJ6zu968T4PNmeqbC-u-DfiKay-4XxurLNASkDz0,18358
16
16
  dara/core/http.py,sha256=-OzbCHlYSnfVnw2492C_UmaWOI5oSONfWk03eEGxSRI,4761
17
17
  dara/core/interactivity/__init__.py,sha256=ZppwTvxaCsaAdf0qX6j1qTcmbj6wxVcbiaMZfwTVKtU,2679
@@ -82,7 +82,7 @@ dara/core/js_tooling/templates/dara.config.json,sha256=RZG_R_xJv_5rYIoz2QZulcG49
82
82
  dara/core/js_tooling/templates/vite.config.template.ts,sha256=W-R9LtXPMv7vQkqMawMmeFrjaQ22xrGU0iYyS_nHkh4,1199
83
83
  dara/core/log_configs/logging.yaml,sha256=YJyD18psAmSVz6587dcEOyoulLuRFFu1g8yMXl1ylM0,706
84
84
  dara/core/logging.py,sha256=8kJPQfRpivxzJXpmsK6-sYnWjR_VBDHzIelD1rstIeM,13260
85
- dara/core/main.py,sha256=h37Ao7opyQm7QIqxKr0YMNkcAGwYE_k9nxM6J04OTJg,20847
85
+ dara/core/main.py,sha256=DtJgblyovl5X_ZEeeQ5Pru1j29GCcnoi9VeO6OZ0qUc,20753
86
86
  dara/core/metrics/__init__.py,sha256=2UqpWHv-Ie58QLJIHJ9Szfjq8xifAuwy5FYGUIFwWtI,823
87
87
  dara/core/metrics/cache.py,sha256=c1PSst_oZZvuVzBXYWdpf8Sbb97u6q0HS2dlsEVLpQU,2632
88
88
  dara/core/metrics/runtime.py,sha256=YP-6Dz0GeI9_Yr7bUk_-OqShyFySGH_AKpDO126l6es,1833
@@ -93,10 +93,10 @@ dara/core/router/compat.py,sha256=WAVzDcJFJOVoIQ5inplIhXD58TWsWwTTebTCqpG4nGs,31
93
93
  dara/core/router/components.py,sha256=MDaiQ8Y0-94EH0Jm4j7p9S141k8G4osSbOKSTSu3aOM,4433
94
94
  dara/core/router/dependency_graph.py,sha256=AyjSk3DuvCgACrgpID4oSpms1X6GQJUbt-scY5X_LN4,2305
95
95
  dara/core/router/router.py,sha256=1r3rFGiftOXC6GP66hKqTdcVNDRJsZWBWvL74wNG4dA,29719
96
- dara/core/umd/dara.core.umd.cjs,sha256=nfYm5XYPXkhx_-RUlfwa2vSadNT3sVYIcYYlHHlT5-Q,5142814
97
- dara/core/umd/style.css,sha256=aywwY47sVAdfUt4q8c3xCi81TuHXoIJdwrWtppRGJrk,4095751
96
+ dara/core/umd/dara.core.umd.cjs,sha256=xWbTSf5MuczWptv2bOgW9Sslvai_3SXNIQq4DR_iCBw,5143689
97
+ dara/core/umd/style.css,sha256=yT3PKpi2sKI2-kQIF8xtVbTPQqgpK7-Ua7tfzDPuSsI,4095881
98
98
  dara/core/visual/__init__.py,sha256=QN0wbG9HPQ_vXh8BO8DnBXeYLIENVTNtRmYzZf1lx7c,577
99
- dara/core/visual/components/__init__.py,sha256=igEOGkaX56VM6IOPLBeG6ru6zMuzHtGIP1zNDB2R8XI,2342
99
+ dara/core/visual/components/__init__.py,sha256=nmCsnMLXeZAjkhMYz-mIFodpVY-69IO1fvwwXbFlMQ4,2447
100
100
  dara/core/visual/components/dynamic_component.py,sha256=w7rxrM9ZTNvkHymkAto_s9UKg7EE8VrlpL9QdRe4sgY,692
101
101
  dara/core/visual/components/fallback.py,sha256=cnuPcblmQ1gyzZHrwHtrD5C5Bo7-JXeiMO0KZ1ACbPM,4764
102
102
  dara/core/visual/components/for_cmp.py,sha256=HykNfue2YzjZjWiWaJakLZmbdd_M7IfUi9kNhG2mLOE,6347
@@ -108,6 +108,7 @@ dara/core/visual/components/progress_tracker.py,sha256=5p_nEJf7RK2oPimXL4YhAN7v0
108
108
  dara/core/visual/components/raw_string.py,sha256=jtG9hDZz3s-sCg__Eg4__XkD80OhnNaWiRo-W88LK4M,921
109
109
  dara/core/visual/components/router_content.py,sha256=ZFJBuT-Vpn4yvbzgt5IGQbBqiWFhYfHa6mgB2O8Xt8I,978
110
110
  dara/core/visual/components/sidebar_frame.py,sha256=vUd8BM-VD3HvI4I1RssS1A2r5-4gtAl-UrMxLdz0sDI,1291
111
+ dara/core/visual/components/theme_provider.py,sha256=cerZVnvQmGHqe_0uIiWXB8U4ArCUQLqWInSOroHim9g,1458
111
112
  dara/core/visual/components/topbar_frame.py,sha256=7L4Bi7Ba_gdfS6yoduXQ3k0-XQaNuahmkumyfzlpzzY,1255
112
113
  dara/core/visual/components/types.py,sha256=uH2IGufr4-I8cNbZgnEd3YbqoPFgyqG91rfNXZVG7a0,686
113
114
  dara/core/visual/css/Property.py,sha256=XJzlMeASyrquhXmaQZvrsgin3xlVfm94dHRY9aJkhXk,43028
@@ -117,10 +118,10 @@ dara/core/visual/progress_updater.py,sha256=IdtWihnMYk8hqsHqDd0nzuuHeQu8wjnZT42s
117
118
  dara/core/visual/template.py,sha256=y0KJU2913Q10y1TVMpTVnIxIoUsabzYfpUHEGuX2QyM,5707
118
119
  dara/core/visual/themes/__init__.py,sha256=aM4mgoIYo2neBSw5FRzswsht7PUKjLthiHLmFIkyRKw,794
119
120
  dara/core/visual/themes/dark.py,sha256=UQGDooOc8ric73eHs9E0ltYP4UCrwqQ3QxqN_fb4PwY,1942
120
- dara/core/visual/themes/definitions.py,sha256=nS_gQvOzCt5hTmj74d0_siq_9QWuj6wNuir4VCHy0Dk,2779
121
+ dara/core/visual/themes/definitions.py,sha256=5g83t24w8Ar51Cl9REBJfCU7_DtlashBQeUTKDg3D1M,2862
121
122
  dara/core/visual/themes/light.py,sha256=-Tviq8oEwGbdFULoDOqPuHO0UpAZGsBy8qFi0kAGolQ,1944
122
- dara_core-1.21.1.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
123
- dara_core-1.21.1.dist-info/METADATA,sha256=EwB6xMLHeQpO34pWrs2FkZxRCmJPX-OjCc8vmf3zSSA,7534
124
- dara_core-1.21.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
125
- dara_core-1.21.1.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
126
- dara_core-1.21.1.dist-info/RECORD,,
123
+ dara_core-1.21.2.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
124
+ dara_core-1.21.2.dist-info/METADATA,sha256=SlVuhAHMJ77CYjCiJKE8xGI0q8IppVGtyMso8jFPckY,7534
125
+ dara_core-1.21.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
+ dara_core-1.21.2.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
127
+ dara_core-1.21.2.dist-info/RECORD,,