dara-core 1.21.10__py3-none-any.whl → 1.21.12__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.
@@ -31,6 +31,7 @@ from typing import (
31
31
  ClassVar,
32
32
  Dict,
33
33
  List,
34
+ Literal,
34
35
  Optional,
35
36
  Tuple,
36
37
  Union,
@@ -438,6 +439,60 @@ class PendingTask(BaseTask):
438
439
  return self.result
439
440
 
440
441
 
442
+ class RouterPath(BaseModel):
443
+ path: Optional[str] = None
444
+ """
445
+ A URL pathname, beginning with '/'.
446
+ """
447
+
448
+ search: Optional[str] = None
449
+ """
450
+ A URL search string, beginning with '?'.
451
+ """
452
+
453
+ hash: Optional[str] = None
454
+ """
455
+ A URL hash string, beginning with '#'.
456
+ """
457
+
458
+
459
+ class NavigateOptions(BaseModel):
460
+ """
461
+ Options for the navigate action
462
+ """
463
+
464
+ replace: bool = False
465
+ """
466
+ Replaces the current entry in the history stack instead of pushing a new one.
467
+
468
+ ```
469
+ # with a history stack like this
470
+ A -> B
471
+
472
+ # normal link click pushes a new entry
473
+ A -> B -> C
474
+
475
+ # but with `replace`, B is replaced by C
476
+ A -> C
477
+ ```
478
+ """
479
+
480
+ relative: Literal['route', 'path'] = 'route'
481
+ """
482
+ Defines the relative path behavior for the link.
483
+
484
+ ```python
485
+ NavigateOptions(to='..') # default, relative='route'
486
+ NavigateOptions(to='..', relative='path')
487
+ ```
488
+
489
+ Consider a route hierarchy where a parent route pattern is "blog" and a child route pattern is "blog/:slug/edit".
490
+ - route — default, resolves the link relative to the route pattern. In the example above, a relative link of "..." will remove both :slug/edit segments back to "/blog".
491
+ - path — relative to the path so "..." will only remove one URL segment up to "/blog/:slug"
492
+ Note that index routes and layout routes do not have paths so they are not included in the relative path calculation.
493
+ """
494
+
495
+
441
496
  class AnnotatedAction(BaseModel):
442
497
  """
443
498
  Represents a single call to an @action-annotated action.
@@ -51,6 +51,8 @@ from dara.core.base_definitions import (
51
51
  ActionImpl,
52
52
  ActionResolverDef,
53
53
  AnnotatedAction,
54
+ NavigateOptions,
55
+ RouterPath,
54
56
  TaskProgressUpdate,
55
57
  )
56
58
  from dara.core.base_definitions import DaraBaseModel as BaseModel
@@ -372,9 +374,15 @@ class NavigateToImpl(ActionImpl):
372
374
 
373
375
  py_name = 'NavigateTo'
374
376
 
375
- url: Optional[str] = None
377
+ url: Union[str, RouterPath]
378
+
376
379
  new_tab: bool = False
377
380
 
381
+ options: Optional[NavigateOptions] = None
382
+ """
383
+ Options for relative navigations
384
+ """
385
+
378
386
 
379
387
  @deprecated('Use @action or `NavigateToImpl` for simple cases')
380
388
  def NavigateTo(
@@ -947,7 +955,9 @@ class ActionCtx:
947
955
  """
948
956
  return await TriggerVariable(variable=variable, force=force).execute(self)
949
957
 
950
- async def navigate(self, url: str, new_tab: bool = False):
958
+ async def navigate(
959
+ self, url: Union[str, RouterPath], new_tab: bool = False, options: Optional[NavigateOptions] = None
960
+ ):
951
961
  """
952
962
  Navigate to a given url
953
963
 
@@ -991,8 +1001,9 @@ class ActionCtx:
991
1001
 
992
1002
  :param url: the url to navigate to
993
1003
  :param new_tab: whether to open the url in a new tab, defaults to False
1004
+ :param options: options for relative navigations, defaults to None
994
1005
  """
995
- return await NavigateToImpl(url=url, new_tab=new_tab).execute(self)
1006
+ return await NavigateToImpl(url=url, new_tab=new_tab, options=options).execute(self)
996
1007
 
997
1008
  async def logout(self):
998
1009
  """
@@ -1,27 +1,16 @@
1
1
  from typing import Annotated, Any, Literal, Optional, Union
2
2
 
3
- from pydantic import BaseModel, BeforeValidator
4
-
5
- from dara.core.definitions import ComponentInstance, JsComponentDef, StyledComponentInstance, transform_raw_css
3
+ from pydantic import BeforeValidator
4
+
5
+ from dara.core.base_definitions import RouterPath
6
+ from dara.core.definitions import (
7
+ ComponentInstance,
8
+ JsComponentDef,
9
+ StyledComponentInstance,
10
+ transform_raw_css,
11
+ )
6
12
  from dara.core.interactivity import ClientVariable
7
-
8
-
9
- class RouterPath(BaseModel):
10
- path: str
11
- """
12
- A URL pathname, beginning with '/'.
13
- """
14
-
15
- search: Optional[str] = None
16
- """
17
- A URL search string, beginning with '?'.
18
- """
19
-
20
- hash: Optional[str] = None
21
- """
22
- A URL hash string, beginning with '#'.
23
- """
24
-
13
+ from dara.core.visual.components import RawString
25
14
 
26
15
  OutletDef = JsComponentDef(name='Outlet', js_module='@darajs/core', py_module='dara.core')
27
16
 
@@ -52,8 +41,35 @@ class Navigate(ComponentInstance):
52
41
  to: Union[str, RouterPath, ClientVariable]
53
42
 
54
43
  replace: bool = False
44
+ """
45
+ Replaces the current entry in the history stack instead of pushing a new one.
46
+
47
+ ```
48
+ # with a history stack like this
49
+ A -> B
50
+
51
+ # normal link click pushes a new entry
52
+ A -> B -> C
53
+
54
+ # but with `replace`, B is replaced by C
55
+ A -> C
56
+ ```
57
+ """
55
58
 
56
59
  relative: Literal['route', 'path'] = 'route'
60
+ """
61
+ Defines the relative path behavior for the link.
62
+
63
+ ```python
64
+ Navigate(to='..') # default, relative='route'
65
+ Navigate(to='..', relative='path')
66
+ ```
67
+
68
+ Consider a route hierarchy where a parent route pattern is "blog" and a child route pattern is "blog/:slug/edit".
69
+ - route — default, resolves the link relative to the route pattern. In the example above, a relative link of "..." will remove both :slug/edit segments back to "/blog".
70
+ - path — relative to the path so "..." will only remove one URL segment up to "/blog/:slug"
71
+ Note that index routes and layout routes do not have paths so they are not included in the relative path calculation.
72
+ """
57
73
 
58
74
 
59
75
  LinkDef = JsComponentDef(name='Link', js_module='@darajs/core', py_module='dara.core')
@@ -121,15 +137,23 @@ class Link(StyledComponentInstance):
121
137
  Can be a string or RouterPath object
122
138
  """
123
139
 
140
+ # core anchor element attributes
141
+ target: Optional[str] = None
142
+ download: Optional[str] = None
143
+ rel: Optional[str] = None
144
+ referrer_policy: Optional[str] = None
145
+
124
146
  active_css: Annotated[Optional[Any], BeforeValidator(transform_raw_css)] = None
125
147
  inactive_css: Annotated[Optional[Any], BeforeValidator(transform_raw_css)] = None
126
148
 
127
- # TODO: add scroll restoration if it works?
128
-
129
- def __init__(self, *children: ComponentInstance, **kwargs):
149
+ def __init__(self, *children: Union[str, ComponentInstance], **kwargs):
130
150
  components = list(children)
131
151
  if 'children' not in kwargs:
132
152
  kwargs['children'] = components
153
+
154
+ if len(kwargs['children']) > 0:
155
+ kwargs['children'] = [RawString(content=x) if isinstance(x, str) else x for x in kwargs['children']]
156
+
133
157
  super().__init__(**kwargs)
134
158
 
135
159
 
@@ -51420,7 +51420,7 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
51420
51420
  }
51421
51421
  function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
51422
51422
  let location2 = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
51423
- let pathname = stripBasename(location2.pathname || "/", basename);
51423
+ let pathname = stripBasename$1(location2.pathname || "/", basename);
51424
51424
  if (pathname == null) {
51425
51425
  return null;
51426
51426
  }
@@ -51712,7 +51712,7 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
51712
51712
  return value;
51713
51713
  }
51714
51714
  }
51715
- function stripBasename(pathname, basename) {
51715
+ function stripBasename$1(pathname, basename) {
51716
51716
  if (basename === "/") return pathname;
51717
51717
  if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
51718
51718
  return null;
@@ -51911,8 +51911,8 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
51911
51911
  reset: void 0,
51912
51912
  location: void 0
51913
51913
  };
51914
- var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
51915
- var isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url);
51914
+ var ABSOLUTE_URL_REGEX$1 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
51915
+ var isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX$1.test(url);
51916
51916
  var defaultMapRouteProperties = (route) => ({
51917
51917
  hasErrorBoundary: Boolean(route.hasErrorBoundary)
51918
51918
  });
@@ -53207,7 +53207,7 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
53207
53207
  const url = createBrowserURLImpl(location2, true);
53208
53208
  isDocumentReload = // Hard reload if it's an absolute URL to a new origin
53209
53209
  url.origin !== routerWindow.location.origin || // Hard reload if it's an absolute URL that does not match our basename
53210
- stripBasename(url.pathname, basename) == null;
53210
+ stripBasename$1(url.pathname, basename) == null;
53211
53211
  }
53212
53212
  if (isDocumentReload) {
53213
53213
  if (replace22) {
@@ -54311,7 +54311,7 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
54311
54311
  let path = resolveTo(
54312
54312
  to ? to : ".",
54313
54313
  getResolveToMatches(contextualMatches),
54314
- stripBasename(location2.pathname, basename) || location2.pathname,
54314
+ stripBasename$1(location2.pathname, basename) || location2.pathname,
54315
54315
  relative === "path"
54316
54316
  );
54317
54317
  if (to == null) {
@@ -55344,7 +55344,7 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
55344
55344
  if (isAbsoluteUrl(location2)) {
55345
55345
  let normalizedLocation = location2;
55346
55346
  let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation);
55347
- let isSameBasename = stripBasename(url.pathname, basename) != null;
55347
+ let isSameBasename = stripBasename$1(url.pathname, basename) != null;
55348
55348
  if (url.origin === currentUrl.origin && isSameBasename) {
55349
55349
  return url.pathname + url.search + url.hash;
55350
55350
  }
@@ -56438,11 +56438,11 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
56438
56438
  return shouldBlock({
56439
56439
  currentLocation: {
56440
56440
  ...currentLocation,
56441
- pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname
56441
+ pathname: stripBasename$1(currentLocation.pathname, basename) || currentLocation.pathname
56442
56442
  },
56443
56443
  nextLocation: {
56444
56444
  ...nextLocation,
56445
- pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname
56445
+ pathname: stripBasename$1(nextLocation.pathname, basename) || nextLocation.pathname
56446
56446
  },
56447
56447
  historyAction
56448
56448
  });
@@ -56905,7 +56905,7 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
56905
56905
  key = "default"
56906
56906
  } = locationProp;
56907
56907
  let locationContext = React__namespace.useMemo(() => {
56908
- let trailingPathname = stripBasename(pathname, basename);
56908
+ let trailingPathname = stripBasename$1(pathname, basename);
56909
56909
  if (trailingPathname == null) {
56910
56910
  return null;
56911
56911
  }
@@ -57216,7 +57216,7 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
57216
57216
  let body;
57217
57217
  if (isFormElement(target)) {
57218
57218
  let attr2 = target.getAttribute("action");
57219
- action = attr2 ? stripBasename(attr2, basename) : null;
57219
+ action = attr2 ? stripBasename$1(attr2, basename) : null;
57220
57220
  method = target.getAttribute("method") || defaultMethod;
57221
57221
  encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
57222
57222
  formData = new FormData(target);
@@ -57228,7 +57228,7 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
57228
57228
  );
57229
57229
  }
57230
57230
  let attr2 = target.getAttribute("formaction") || form.getAttribute("action");
57231
- action = attr2 ? stripBasename(attr2, basename) : null;
57231
+ action = attr2 ? stripBasename$1(attr2, basename) : null;
57232
57232
  method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
57233
57233
  encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
57234
57234
  formData = new FormData(form, target);
@@ -58255,7 +58255,7 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
58255
58255
  ) : reqUrl;
58256
58256
  if (url.pathname === "/") {
58257
58257
  url.pathname = `_root.${extension}`;
58258
- } else if (basename && stripBasename(url.pathname, basename) === "/") {
58258
+ } else if (basename && stripBasename$1(url.pathname, basename) === "/") {
58259
58259
  url.pathname = `${basename.replace(/\/$/, "")}/_root.${extension}`;
58260
58260
  } else {
58261
58261
  url.pathname = `${url.pathname.replace(/\/$/, "")}.${extension}`;
@@ -60069,7 +60069,7 @@ import(${JSON.stringify(manifest.entry.module)});`;
60069
60069
  try {
60070
60070
  let currentUrl = new URL(window.location.href);
60071
60071
  let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
60072
- let path = stripBasename(targetUrl.pathname, basename);
60072
+ let path = stripBasename$1(targetUrl.pathname, basename);
60073
60073
  if (targetUrl.origin === currentUrl.origin && path != null) {
60074
60074
  to = path + targetUrl.search + targetUrl.hash;
60075
60075
  } else {
@@ -60149,7 +60149,7 @@ import(${JSON.stringify(manifest.entry.module)});`;
60149
60149
  toPathname = toPathname.toLowerCase();
60150
60150
  }
60151
60151
  if (nextLocationPathname && basename) {
60152
- nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
60152
+ nextLocationPathname = stripBasename$1(nextLocationPathname, basename) || nextLocationPathname;
60153
60153
  }
60154
60154
  const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
60155
60155
  let isActive = locationPathname === toPathname || !end2 && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
@@ -60541,7 +60541,7 @@ import(${JSON.stringify(manifest.entry.module)});`;
60541
60541
  key = getKey(
60542
60542
  {
60543
60543
  ...location2,
60544
- pathname: stripBasename(location2.pathname, basename) || location2.pathname
60544
+ pathname: stripBasename$1(location2.pathname, basename) || location2.pathname
60545
60545
  },
60546
60546
  matches2
60547
60547
  );
@@ -60704,8 +60704,8 @@ import(${JSON.stringify(manifest.entry.module)});`;
60704
60704
  if (!vtContext.isTransitioning) {
60705
60705
  return false;
60706
60706
  }
60707
- let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
60708
- let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
60707
+ let currentPath = stripBasename$1(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
60708
+ let nextPath = stripBasename$1(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
60709
60709
  return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
60710
60710
  }
60711
60711
  function StaticRouter({
@@ -62164,7 +62164,7 @@ import(${JSON.stringify(manifest.entry.module)});`;
62164
62164
  function getSingleFetchRedirect(status, headers, basename) {
62165
62165
  let redirect2 = headers.get("Location");
62166
62166
  if (basename) {
62167
- redirect2 = stripBasename(redirect2, basename) || redirect2;
62167
+ redirect2 = stripBasename$1(redirect2, basename) || redirect2;
62168
62168
  }
62169
62169
  return {
62170
62170
  redirect: redirect2,
@@ -62291,19 +62291,19 @@ import(${JSON.stringify(manifest.entry.module)});`;
62291
62291
  let url = new URL(request2.url);
62292
62292
  let normalizedBasename = _build.basename || "/";
62293
62293
  let normalizedPath = url.pathname;
62294
- if (stripBasename(normalizedPath, normalizedBasename) === "/_root.data") {
62294
+ if (stripBasename$1(normalizedPath, normalizedBasename) === "/_root.data") {
62295
62295
  normalizedPath = normalizedBasename;
62296
62296
  } else if (normalizedPath.endsWith(".data")) {
62297
62297
  normalizedPath = normalizedPath.replace(/\.data$/, "");
62298
62298
  }
62299
- if (stripBasename(normalizedPath, normalizedBasename) !== "/" && normalizedPath.endsWith("/")) {
62299
+ if (stripBasename$1(normalizedPath, normalizedBasename) !== "/" && normalizedPath.endsWith("/")) {
62300
62300
  normalizedPath = normalizedPath.slice(0, -1);
62301
62301
  }
62302
62302
  let isSpaMode = getBuildTimeHeader(request2, "X-React-Router-SPA-Mode") === "yes";
62303
62303
  if (!_build.ssr) {
62304
62304
  let decodedPath = decodeURI(normalizedPath);
62305
62305
  if (normalizedBasename !== "/") {
62306
- let strippedPath = stripBasename(decodedPath, normalizedBasename);
62306
+ let strippedPath = stripBasename$1(decodedPath, normalizedBasename);
62307
62307
  if (strippedPath == null) {
62308
62308
  errorHandler(
62309
62309
  new ErrorResponseImpl(
@@ -74769,30 +74769,54 @@ body,
74769
74769
  const root = clientExports.createRoot(container);
74770
74770
  root.render(/* @__PURE__ */ React.createElement(Root, { daraData, queryClient, importers }));
74771
74771
  }
74772
- function isValidHttpUrl(url) {
74773
- if (url.startsWith("/")) {
74774
- return true;
74772
+ function getBasename() {
74773
+ if (window.dara.base_url !== "") {
74774
+ return new URL(window.dara.base_url, window.origin).pathname;
74775
74775
  }
74776
- let newUrl;
74777
- try {
74778
- newUrl = new URL(url);
74779
- } catch {
74780
- return false;
74776
+ return "/";
74777
+ }
74778
+ const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
74779
+ function stripBasename(pathname, basename) {
74780
+ if (basename === "/") {
74781
+ return pathname;
74782
+ }
74783
+ if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
74784
+ return null;
74785
+ }
74786
+ const startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
74787
+ const nextChar = pathname.charAt(startIndex);
74788
+ if (nextChar && nextChar !== "/") {
74789
+ return null;
74781
74790
  }
74782
- return newUrl.protocol === "http:" || newUrl.protocol === "https:";
74791
+ return pathname.slice(startIndex) || "/";
74783
74792
  }
74784
74793
  const NavigateTo = (ctx, actionImpl) => {
74785
- const isValidUrl = isValidHttpUrl(actionImpl.url);
74786
- if (!isValidUrl) {
74787
- throw new Error(`Invalid URL: ${actionImpl.url}`);
74788
- }
74789
- if (actionImpl.new_tab) {
74790
- window.open(actionImpl.url, actionImpl.new_tab ? "_blank" : void 0);
74791
- } else if (actionImpl.url.startsWith("/")) {
74792
- ctx.navigate(actionImpl.url);
74793
- } else {
74794
- window.location.href = actionImpl.url;
74794
+ const basename = getBasename();
74795
+ let isExternal = false;
74796
+ let to = actionImpl.url;
74797
+ if (typeof actionImpl.url === "string" && ABSOLUTE_URL_REGEX.test(actionImpl.url)) {
74798
+ try {
74799
+ const currentUrl = new URL(window.location.href);
74800
+ const targetUrl = new URL(actionImpl.url);
74801
+ const path = stripBasename(targetUrl.pathname, basename);
74802
+ if (targetUrl.origin === currentUrl.origin && path != null) {
74803
+ to = path + targetUrl.search + targetUrl.hash;
74804
+ } else {
74805
+ isExternal = true;
74806
+ }
74807
+ } catch {
74808
+ throw new Error(`Invalid URL: ${actionImpl.url}`);
74809
+ }
74810
+ }
74811
+ if (isExternal && typeof to === "string") {
74812
+ if (actionImpl.new_tab) {
74813
+ window.open(to, "_blank");
74814
+ } else {
74815
+ window.location.href = to;
74816
+ }
74817
+ return;
74795
74818
  }
74819
+ ctx.navigate(to, actionImpl.options);
74796
74820
  };
74797
74821
  const ResetVariables = (ctx, actionImpl) => {
74798
74822
  actionImpl.variables.filter(isVariable).forEach((variable) => {
@@ -98334,7 +98358,11 @@ body,
98334
98358
  inactiveStyle,
98335
98359
  onMouseMove: props.prefetch ? handleMouseMove : void 0,
98336
98360
  onFocus: props.prefetch ? handleFocus : void 0,
98337
- onTouchStart: props.prefetch ? handleTouchStart : void 0
98361
+ onTouchStart: props.prefetch ? handleTouchStart : void 0,
98362
+ download: props.download,
98363
+ referrerPolicy: props.referrer_policy,
98364
+ target: props.target,
98365
+ rel: props.rel
98338
98366
  },
98339
98367
  props.children.map((child, idx) => /* @__PURE__ */ React__namespace.createElement(DynamicComponent$1, { component: child, key: idx }))
98340
98368
  ));
@@ -98708,6 +98736,7 @@ body,
98708
98736
  exports.ImportersCtx = importersCtx;
98709
98737
  exports.Link = Link;
98710
98738
  exports.LoaderError = LoaderError;
98739
+ exports.LockSecuredCache = SingleUseCache;
98711
98740
  exports.Menu = Menu;
98712
98741
  exports.MenuLink = MenuLink;
98713
98742
  exports.Navigate = Navigate;
@@ -98723,6 +98752,9 @@ body,
98723
98752
  exports.RequestExtrasCtx = requestExtrasCtx;
98724
98753
  exports.RequestExtrasProvider = RequestExtrasProvider;
98725
98754
  exports.ResetVariables = ResetVariables;
98755
+ exports.RouteContentDisplay = RouteContent;
98756
+ exports.RouterContextProvider = RouterContextProvider;
98757
+ exports.RouterRoot = RouterRoot;
98726
98758
  exports.RowFallback = RowFallback;
98727
98759
  exports.ServerVariableSyncProvider = ServerVariableSyncProvider;
98728
98760
  exports.SideBarFrame = SideBarFrame;
@@ -98744,14 +98776,20 @@ body,
98744
98776
  exports.clearCaches_TEST = clearCaches_TEST;
98745
98777
  exports.clearRegistries_TEST = clearRegistries_TEST;
98746
98778
  exports.combineFilters = combineFilters;
98779
+ exports.createRouteLoader = createRouteLoader;
98780
+ exports.createRouter = createRouter;
98747
98781
  exports.default = run;
98748
98782
  exports.deferred = deferred;
98749
98783
  exports.depsRegistry = depsRegistry;
98750
98784
  exports.fetchDerivedVariable = fetchDerivedVariable;
98785
+ exports.fetchRouteData = fetchRouteData;
98751
98786
  exports.fetchTabularServerVariable = fetchTabularServerVariable;
98752
98787
  exports.fetchTaskResult = fetchTaskResult;
98788
+ exports.findFirstPath = findFirstPath;
98789
+ exports.getBasename = getBasename;
98753
98790
  exports.getComponentRegistryKey = getComponentRegistryKey;
98754
98791
  exports.getDeps = getDeps;
98792
+ exports.getFromPreloadCache = getFromPreloadCache;
98755
98793
  exports.getIcon = getIcon;
98756
98794
  exports.getOrRegisterDerivedVariable = getOrRegisterDerivedVariable;
98757
98795
  exports.getOrRegisterDerivedVariableResult = getOrRegisterDerivedVariableResult;
@@ -98820,11 +98858,13 @@ body,
98820
98858
  exports.useFetchTabularDerivedVariable = useFetchTabularDerivedVariable;
98821
98859
  exports.useFetchTabularServerVariable = useFetchTabularServerVariable;
98822
98860
  exports.useInterval = useInterval;
98861
+ exports.usePreloadRoute = usePreloadRoute;
98823
98862
  exports.usePrevious = usePrevious$1;
98824
98863
  exports.useRefreshSelector = useRefreshSelector;
98825
98864
  exports.useRefreshServerComponent = useRefreshServerComponent;
98826
98865
  exports.useRegistriesCtx = useRegistriesCtx;
98827
98866
  exports.useRequestExtras = useRequestExtras;
98867
+ exports.useRouterContext = useRouterContext;
98828
98868
  exports.useSession = useSession;
98829
98869
  exports.useSessionToken = useSessionToken;
98830
98870
  exports.useSwitchVariable = useSwitchVariable;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dara-core
3
- Version: 1.21.10
3
+ Version: 1.21.12
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.10)
24
+ Requires-Dist: create-dara-app (==1.21.12)
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.10) ; extra == "all"
27
+ Requires-Dist: dara-components (==1.21.12) ; 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.10/img/dara_light.svg?raw=true">
58
+ <img src="https://github.com/causalens/dara/blob/v1.21.12/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.10/img/components_gallery.png?raw=true)
103
+ ![Dara App](https://github.com/causalens/dara/blob/v1.21.12/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.10/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.10/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.10/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.12/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.12/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.12/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.10/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.12/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.10/LICENSE).
153
+ Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.21.12/LICENSE).
154
154
 
@@ -6,7 +6,7 @@ dara/core/auth/basic.py,sha256=8ebWpHx53ObkuzTHIKSRdtsmKq0R5v8RuQXhZcnpTsA,4933
6
6
  dara/core/auth/definitions.py,sha256=wTsFWzX7bGHTU_vxGW50pqcmB_AmhETIIUdGB5UrMBU,3467
7
7
  dara/core/auth/routes.py,sha256=0o5KXApRbkL0F5qFsarQk_cq5lbQ3QfIHR_mwLRgBEY,7217
8
8
  dara/core/auth/utils.py,sha256=iEWP5qwfH17Mi-5t3sP-DNMUrWN0oSRk96NhieY2Zw4,7334
9
- dara/core/base_definitions.py,sha256=ptc6OSx-qElWWSuZB4-06kWmnj6hekpKR47eeB36igQ,16915
9
+ dara/core/base_definitions.py,sha256=wDeXoKro7WcMB8RXImaAZrwbBYdhnN_jgd2s7eDDO2M,18386
10
10
  dara/core/cli.py,sha256=V__LAK3ozWGsVTEQHqvJwqSfpC3o6R76YGABJ-YVoSE,8185
11
11
  dara/core/configuration.py,sha256=caPebHNUmYqh9czEBwQiIDjGrH8ltsphayZICj1CRhc,23489
12
12
  dara/core/css.py,sha256=UkNZ6n7RDBLsHmpZvn_a3K2nAwxVggQJbQMKNbgXONA,1753
@@ -15,7 +15,7 @@ dara/core/defaults.py,sha256=y-PU4DhF3uEEfrFmlJnenM8jhnQDTDaOU5kuAYZE2gw,4740
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
18
- dara/core/interactivity/actions.py,sha256=ADLVhffplOcIWy7l74SrpZk8oCe3q12BJ9060rVDpfU,48170
18
+ dara/core/interactivity/actions.py,sha256=_guOKc5VkXH1J91-pdTeIQumCFHkve6G0ES5rFBm1vY,48478
19
19
  dara/core/interactivity/any_data_variable.py,sha256=GhT6lzCDRlQtYG2gNNUHq4th7K3RacqDfkjaq7o4mCc,317
20
20
  dara/core/interactivity/any_variable.py,sha256=b6aMOZZc9Q4IFPPjuIbFgqYdw52-6QRsxNRj5ohZeL0,13648
21
21
  dara/core/interactivity/client_variable.py,sha256=bFc4gmKKVfAvZHmv5Y2ME1VMTxSM_v_0lcmyRNTLOKk,2320
@@ -90,10 +90,10 @@ dara/core/metrics/utils.py,sha256=inR1Ab5hmWZY2lsgGwLCQOEdyhCD9PumU52X2JbwlKY,22
90
90
  dara/core/persistence.py,sha256=ZUmfAjcTwk_oYyaulDrtpiCwIg8vaOw8uTZd2qT4nNo,19410
91
91
  dara/core/router/__init__.py,sha256=yGI_MgLQU37ircCtYVNjnhqCjWQxKd5amoNqvMyrhOs,121
92
92
  dara/core/router/compat.py,sha256=WAVzDcJFJOVoIQ5inplIhXD58TWsWwTTebTCqpG4nGs,3137
93
- dara/core/router/components.py,sha256=K6bj04_ZPJcU9JQjaxPJkbUeaHtA_jeJNEvCqQbDf3A,5090
93
+ dara/core/router/components.py,sha256=lnh8dCin6BunI0KILdua-zJZOuwbDbniLGb6eF_V9hM,6183
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=9t6qlKqYJkfS0d3UVmxSYLRdpBuyjPCcw8hmMTOjyms,5150509
96
+ dara/core/umd/dara.core.umd.cjs,sha256=KXoJu_06chU79sKcrZPHoEvtC7o20QLfE98puoxlvcA,5152119
97
97
  dara/core/umd/style.css,sha256=yT3PKpi2sKI2-kQIF8xtVbTPQqgpK7-Ua7tfzDPuSsI,4095881
98
98
  dara/core/visual/__init__.py,sha256=QN0wbG9HPQ_vXh8BO8DnBXeYLIENVTNtRmYzZf1lx7c,577
99
99
  dara/core/visual/components/__init__.py,sha256=nmCsnMLXeZAjkhMYz-mIFodpVY-69IO1fvwwXbFlMQ4,2447
@@ -120,8 +120,8 @@ dara/core/visual/themes/__init__.py,sha256=aM4mgoIYo2neBSw5FRzswsht7PUKjLthiHLmF
120
120
  dara/core/visual/themes/dark.py,sha256=UQGDooOc8ric73eHs9E0ltYP4UCrwqQ3QxqN_fb4PwY,1942
121
121
  dara/core/visual/themes/definitions.py,sha256=5g83t24w8Ar51Cl9REBJfCU7_DtlashBQeUTKDg3D1M,2862
122
122
  dara/core/visual/themes/light.py,sha256=-Tviq8oEwGbdFULoDOqPuHO0UpAZGsBy8qFi0kAGolQ,1944
123
- dara_core-1.21.10.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
124
- dara_core-1.21.10.dist-info/METADATA,sha256=VAhABX4vYo75FUCasEESdpTEH68xH9l-QojyabNf3BI,7544
125
- dara_core-1.21.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
- dara_core-1.21.10.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
127
- dara_core-1.21.10.dist-info/RECORD,,
123
+ dara_core-1.21.12.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
124
+ dara_core-1.21.12.dist-info/METADATA,sha256=grTJrNqVMQk1Da7XU6IVNt7Jrf1TidbxBbRnISdHPn8,7544
125
+ dara_core-1.21.12.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
+ dara_core-1.21.12.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
127
+ dara_core-1.21.12.dist-info/RECORD,,