ex4nicegui 0.6.5__py3-none-any.whl → 0.6.6__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.
ex4nicegui/__init__.py CHANGED
@@ -20,7 +20,7 @@ from ex4nicegui.utils.signals import (
20
20
  is_reactive,
21
21
  )
22
22
  from ex4nicegui.utils.asyncComputed import async_computed
23
-
23
+ from ex4nicegui.utils.clientScope import new_scope
24
24
 
25
25
  __all__ = [
26
26
  "async_computed",
@@ -43,6 +43,7 @@ __all__ = [
43
43
  "batch",
44
44
  "to_raw",
45
45
  "is_setter_ref",
46
+ "new_scope",
46
47
  ]
47
48
 
48
- __version__ = "0.6.5"
49
+ __version__ = "0.6.6"
@@ -2,10 +2,7 @@ from __future__ import annotations
2
2
  from typing import TYPE_CHECKING, Any, Callable, Dict, Union, cast
3
3
  from nicegui.events import UiEventArguments
4
4
  from ex4nicegui.reactive import rxui
5
- from ex4nicegui.reactive.EChartsComponent.ECharts import (
6
- EChartsMouseEventArguments,
7
- echarts,
8
- )
5
+ from ex4nicegui.reactive.EChartsComponent.ECharts import echarts
9
6
  from nicegui import ui
10
7
  from ex4nicegui.bi.dataSource import DataSource
11
8
  from .models import UiResult
@@ -21,7 +18,7 @@ class EChartsResult(UiResult[echarts]):
21
18
  super().__init__(element, dataSource)
22
19
  self.chart_update = chart_update
23
20
 
24
- def on_chart_click(self, handler: Callable[[EChartsMouseEventArguments], Any]):
21
+ def on_chart_click(self, handler: Callable[[UiEventArguments], Any]):
25
22
  return self.element.echarts_on("click", handler)
26
23
 
27
24
  def on_chart_click_blank(self, handler: Callable[[UiEventArguments], Any]):
@@ -1,83 +1,79 @@
1
1
  import { convertDynamicProperties } from "../../static/utils/dynamic_properties.js";
2
2
 
3
+ function collectMapRegisterTask() {
4
+ const tasks = new Map();
3
5
 
4
- function retry(fn, options = {}) {
6
+ if (typeof window.ex4ngEchartsMapTasks !== "undefined") {
5
7
 
6
- options = {
7
- error: 'Maximum number of tries exceeded',
8
- tryMaxTimes: 5,
9
- intervalMs: 800,
10
- ...options
11
- }
8
+ for (const [mapName, src] of window.ex4ngEchartsMapTasks.entries()) {
9
+
10
+ const registerPromise = new Promise((resolve, reject) => {
11
+ fetch(src)
12
+ .then((response) => response.json())
13
+ .then((data) => {
14
+ echarts.registerMap(mapName, data);
15
+ resolve();
16
+ });
12
17
 
13
- let tryTimes = 0
14
- let isDone = false
18
+ });
15
19
 
16
- const doneFn = () => {
17
- isDone = true
20
+ tasks.set(mapName, registerPromise);
21
+ }
18
22
  }
19
23
 
20
- function callback() {
21
- tryTimes += 1
24
+ return tasks;
25
+ }
22
26
 
23
- if (tryTimes <= options.tryMaxTimes) {
24
- fn(doneFn)
27
+ function hasMapOrGeo(options) {
28
+ if (options) {
29
+ const hasMapSeries = options.series && Array.isArray(options.series) &&
30
+ options.series.some(seriesItem =>
31
+ seriesItem.type === 'map' ||
32
+ seriesItem.type === 'lines'
33
+ );
25
34
 
26
- if (isDone) {
27
- clearInterval(task)
28
- }
29
-
30
- } else {
31
- console.error(options.error)
32
- clearInterval(task)
33
- }
35
+ const hasGeoConfig = options.geo && (typeof options.geo === 'object' || Array.isArray(options.geo));
34
36
 
37
+ return hasMapSeries || hasGeoConfig;
35
38
  }
36
-
37
- callback();
38
- const task = setInterval(callback, options.intervalMs);
39
+ return false;
39
40
  }
40
41
 
42
+ const mapRegisterTasks = collectMapRegisterTask();
41
43
 
42
44
  export default {
43
45
  template: "<div></div>",
44
- mounted() {
46
+ async mounted() {
47
+ await this.$nextTick(); // wait for Tailwind classes to be applied
45
48
 
46
- function initChart() {
47
- this.chart = echarts.init(this.$el, this.theme);
49
+ if (hasMapOrGeo(this.options)) {
50
+ await Promise.all(Array.from(mapRegisterTasks.values()));
51
+ }
48
52
 
49
- if (this.options) {
50
- this.update_chart();
51
- } else {
52
- const fn = new Function('return ' + this.code)()
53
- fn(this.chart)
54
- this.$emit("__update_options_from_client", this.chart.getOption())
55
- }
56
- this.chart.getZr().on("click", (e) => {
57
- if (!e.target) {
58
- this.$emit("clickBlank")
59
- }
60
- });
61
- this.resizeObs = new ResizeObserver(this.chart.resize)
53
+ this.chart = echarts.init(this.$el, this.theme);
54
+
55
+ this.resizeObs = new ResizeObserver(this.chart.resize)
56
+
57
+ // Prevent interruption of chart animations due to resize operations.
58
+ // It is recommended to register the callbacks for such an event before setOption.
59
+ const createResizeObserver = () => {
62
60
  this.resizeObs.observe(this.$el);
63
- }
61
+ this.chart.off("finished", createResizeObserver);
62
+ };
63
+ this.chart.on("finished", createResizeObserver);
64
64
 
65
- initChart = initChart.bind(this)
66
-
67
- retry((done) => {
68
- try {
69
- initChart()
70
- done()
71
- } catch (e) {
72
- if (e instanceof TypeError && e.message === `Cannot read properties of undefined (reading 'regions')`) {
73
- echarts.dispose(this.chart)
74
- return
75
- } else {
76
- done()
77
- throw e;
78
- }
65
+ if (this.options) {
66
+ this.update_chart();
67
+ } else {
68
+ const fn = new Function('return ' + this.code)()
69
+ fn(this.chart)
70
+ this.$emit("__update_options_from_client", this.chart.getOption())
71
+ }
72
+ this.chart.getZr().on("click", (e) => {
73
+ if (!e.target) {
74
+ this.$emit("clickBlank")
79
75
  }
80
- }, { error: 'Maximum number of retries echart init' })
76
+ });
81
77
 
82
78
  },
83
79
  beforeDestroy() {
@@ -94,33 +90,10 @@ export default {
94
90
  this.chart.setOption(this.options, opts ?? { notMerge: this.chart.options?.series.length != this.options.series.length });
95
91
  },
96
92
 
97
-
98
- echarts_on(eventName, query, callbackId) {
99
-
100
- retry((done) => {
101
- if (this.chart) {
102
-
103
- this.chart.on(eventName, query, (e) => {
104
- const eventParams = {
105
- componentType: e.componentType,
106
- seriesType: e.seriesType,
107
- seriesIndex: e.seriesIndex,
108
- seriesName: e.seriesName,
109
- name: e.name,
110
- dataIndex: e.dataIndex,
111
- data: e.data,
112
- dataType: e.dataType,
113
- value: e.value,
114
- color: e.color,
115
- }
116
-
117
- this.$emit('event_on', { params: eventParams, callbackId })
118
- })
119
-
120
- done()
121
- }
122
- }, { error: 'Maximum number of retries on echarts event' })
123
-
93
+ echarts_on(eventName, query) {
94
+ this.chart.on(eventName.replace(/^chart:/, ''), query, (e) => {
95
+ this.$emit(eventName, e);
96
+ });
124
97
  },
125
98
 
126
99
  run_chart_method(name, ...args) {
@@ -128,7 +101,7 @@ export default {
128
101
  name = name.slice(1);
129
102
  args = args.map((arg) => new Function("return " + arg)());
130
103
  }
131
- return this.chart[name](...args);
104
+ return runMethod(this.chart, name, args);
132
105
  },
133
106
  },
134
107
  props: {
@@ -3,70 +3,26 @@ from typing import (
3
3
  Any,
4
4
  Callable,
5
5
  Dict,
6
- List,
7
6
  Optional,
8
7
  Union,
9
8
  )
10
- from typing_extensions import Literal
11
- from dataclasses import dataclass
12
- from nicegui.dataclasses import KWONLY_SLOTS
13
- from nicegui.events import (
14
- handle_event,
15
- UiEventArguments,
16
- )
9
+
10
+ from nicegui.events import handle_event, UiEventArguments, GenericEventArguments
17
11
  from nicegui.element import Element
18
12
  from nicegui.awaitable_response import AwaitableResponse
19
- from nicegui import ui
20
13
  from pathlib import Path
21
14
  import nicegui
22
- import uuid
15
+
16
+ from .types import (
17
+ _T_event_name,
18
+ )
19
+ from ex4nicegui.reactive.deferredTask import DeferredTask
20
+ from .utils import get_bound_event_args, create_event_handler_args
23
21
 
24
22
  NG_ROOT = Path(nicegui.__file__).parent / "elements"
25
23
  libraries = [NG_ROOT / "lib/echarts/echarts.min.js"]
26
24
 
27
25
 
28
- _Chart_Click_Args = [
29
- "componentType",
30
- "seriesType",
31
- "seriesIndex",
32
- "seriesName",
33
- "name",
34
- "dataIndex",
35
- "data",
36
- "dataType",
37
- "value",
38
- "color",
39
- ]
40
-
41
-
42
- @dataclass(**KWONLY_SLOTS)
43
- class EChartsMouseEventArguments(UiEventArguments):
44
- componentType: str
45
- seriesType: str
46
- seriesIndex: int
47
- seriesName: str
48
- name: str
49
- dataIndex: int
50
- data: dict
51
- dataType: Optional[str]
52
- value: Any
53
- color: str
54
-
55
-
56
- _T_echats_on_callback = Callable[[EChartsMouseEventArguments], Any]
57
- _T_mouse_event_name = Literal[
58
- "click",
59
- "dblclick",
60
- "mousedown",
61
- "mousemove",
62
- "mouseup",
63
- "mouseover",
64
- "mouseout",
65
- "globalout",
66
- "contextmenu",
67
- ]
68
-
69
-
70
26
  class echarts(Element, component="ECharts.js", libraries=libraries): # type: ignore
71
27
  def __init__(
72
28
  self,
@@ -74,6 +30,7 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
74
30
  code: Optional[str] = None,
75
31
  ) -> None:
76
32
  super().__init__()
33
+ self.__deferred_task = DeferredTask()
77
34
 
78
35
  if (options is None) and (bool(code) is False):
79
36
  raise ValueError("At least one of options and code must be valid.")
@@ -89,36 +46,6 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
89
46
  self._props["options"] = options
90
47
  self._props["code"] = code
91
48
 
92
- self._echarts_on_tasks: List[Callable] = []
93
- self._echarts_on_callback_map: Dict[str, _T_echats_on_callback] = {}
94
-
95
- async def on_client_connect(
96
- client: nicegui.Client,
97
- ) -> Any:
98
- await client.connected()
99
-
100
- for func in self._echarts_on_tasks:
101
- func()
102
-
103
- client.connect_handlers.remove(on_client_connect) # type: ignore
104
-
105
- ui.context.client.on_connect(on_client_connect)
106
-
107
- def echartsOn_handler(e):
108
- callbackId = e.args["callbackId"]
109
- params: Dict = e.args["params"]
110
- params["dataType"] = params.get("dataType")
111
-
112
- if callbackId in self._echarts_on_callback_map:
113
- event_args = EChartsMouseEventArguments(
114
- sender=e.sender, client=e.client, **params
115
- )
116
- handler = self._echarts_on_callback_map[callbackId]
117
-
118
- handle_event(handler, event_args)
119
-
120
- self.on("event_on", echartsOn_handler)
121
-
122
49
  def update_chart(
123
50
  self,
124
51
  merge_opts: Optional[dict] = None,
@@ -164,34 +91,24 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
164
91
  ),
165
92
  )
166
93
 
167
- self.on(
168
- "clickBlank",
169
- inner_handler,
170
- _Chart_Click_Args,
171
- )
94
+ self.on("clickBlank", inner_handler)
172
95
 
173
96
  def echarts_on(
174
97
  self,
175
- event_name: _T_mouse_event_name,
176
- handler: _T_echats_on_callback,
98
+ event_name: _T_event_name,
99
+ handler: Callable[[UiEventArguments], None],
177
100
  query: Optional[Union[str, Dict]] = None,
178
101
  ):
179
- if not ui.context.client.has_socket_connection:
102
+ def org_handler(e: GenericEventArguments) -> None:
103
+ event_args = create_event_handler_args(event_name, e)
104
+ handle_event(handler, event_args)
180
105
 
181
- def task_func():
182
- self.echarts_on(event_name, handler, query)
106
+ ui_event_name = f"chart:{event_name}"
107
+ super().on(ui_event_name, org_handler, args=get_bound_event_args(event_name))
183
108
 
184
- self._echarts_on_tasks.append(task_func)
185
- return
186
-
187
- callback_id = uuid.uuid4().hex
188
- self.run_method(
189
- "echarts_on",
190
- event_name,
191
- query,
192
- callback_id,
193
- )
194
- self._echarts_on_callback_map[callback_id] = handler
109
+ @self.__deferred_task.register
110
+ def _():
111
+ self.run_method("echarts_on", ui_event_name, query)
195
112
 
196
113
  def run_chart_method(
197
114
  self, name: str, *args, timeout: float = 1, check_interval: float = 0.01
@@ -0,0 +1,26 @@
1
+ from typing import (
2
+ Any,
3
+ Optional,
4
+ )
5
+ from dataclasses import dataclass, fields
6
+ from nicegui.dataclasses import KWONLY_SLOTS
7
+ from nicegui.events import (
8
+ UiEventArguments,
9
+ )
10
+
11
+
12
+ @dataclass(**KWONLY_SLOTS)
13
+ class EChartsMouseEventArguments(UiEventArguments):
14
+ componentType: str
15
+ seriesType: str
16
+ seriesIndex: int
17
+ seriesName: str
18
+ name: str
19
+ dataIndex: int
20
+ data: dict
21
+ dataType: Optional[str]
22
+ value: Any
23
+ color: str
24
+
25
+
26
+ _Mouse_Event_Arguments_Fields = [f.name for f in fields(EChartsMouseEventArguments)]
@@ -0,0 +1,51 @@
1
+ from typing import (
2
+ Union,
3
+ )
4
+ from typing_extensions import Literal
5
+
6
+
7
+ _T_mouse_event_name = Literal[
8
+ "click",
9
+ "dblclick",
10
+ "mousedown",
11
+ "mousemove",
12
+ "mouseup",
13
+ "mouseover",
14
+ "mouseout",
15
+ "globalout",
16
+ "contextmenu",
17
+ ]
18
+
19
+ _T_generic_event_name = Literal[
20
+ "highlight",
21
+ "downplay",
22
+ "selectchanged",
23
+ "legendselectchanged",
24
+ "legendselected",
25
+ "legendunselected",
26
+ "legendselectall",
27
+ "legendinverseselect",
28
+ "legendscroll",
29
+ "datazoom",
30
+ "datarangeselected",
31
+ "graphroam",
32
+ "georoam",
33
+ "treeroam",
34
+ "timelinechanged",
35
+ "timelineplaychanged",
36
+ "restore",
37
+ "dataviewchanged",
38
+ "magictypechanged",
39
+ "geoselectchanged",
40
+ "geoselected",
41
+ "geounselected",
42
+ "axisareaselected",
43
+ "brush",
44
+ "brushEnd",
45
+ "brushselected",
46
+ "globalcursortaken",
47
+ "rendered",
48
+ "finished",
49
+ ]
50
+
51
+ _T_event_name = Union[_T_mouse_event_name, _T_generic_event_name]
@@ -0,0 +1,44 @@
1
+ from typing import List, Optional
2
+ import typing
3
+ from .types import _T_event_name, _T_mouse_event_name
4
+ from .events import EChartsMouseEventArguments, _Mouse_Event_Arguments_Fields
5
+ from nicegui.events import UiEventArguments, GenericEventArguments
6
+ from functools import lru_cache
7
+
8
+
9
+ @lru_cache(maxsize=1)
10
+ def _get_mouse_event_names():
11
+ return set(typing.get_args(_T_mouse_event_name))
12
+
13
+
14
+ def is_mouse_event(event_name: _T_event_name) -> bool:
15
+ return event_name in _get_mouse_event_names()
16
+
17
+
18
+ def get_bound_event_args(event_name: _T_event_name) -> Optional[List[str]]:
19
+ if is_mouse_event(event_name):
20
+ return _Mouse_Event_Arguments_Fields
21
+
22
+ return None
23
+
24
+
25
+ def create_event_handler_args(
26
+ event_name: _T_event_name, e: GenericEventArguments
27
+ ) -> UiEventArguments:
28
+ if is_mouse_event(event_name):
29
+ return EChartsMouseEventArguments(
30
+ sender=e.sender,
31
+ client=e.client,
32
+ componentType=e.args["componentType"],
33
+ seriesType=e.args["seriesType"],
34
+ seriesIndex=e.args["seriesIndex"],
35
+ seriesName=e.args["seriesName"],
36
+ name=e.args["name"],
37
+ dataIndex=e.args["dataIndex"],
38
+ data=e.args["data"],
39
+ dataType=e.args.get("dataType"),
40
+ value=e.args["value"],
41
+ color=e.args["color"],
42
+ )
43
+
44
+ return GenericEventArguments(sender=e.sender, client=e.client, args=e.args)
@@ -0,0 +1,29 @@
1
+ from typing import Callable
2
+ from nicegui import ui, Client as ng_client
3
+
4
+
5
+ class DeferredTask:
6
+ def __init__(self):
7
+ self._tasks = []
8
+
9
+ async def on_client_connect(
10
+ client: ng_client,
11
+ ):
12
+ await client.connected()
13
+
14
+ for task in self._tasks:
15
+ task()
16
+
17
+ self._tasks.clear()
18
+
19
+ # Avoid events becoming ineffective due to page refresh when sharing the client.
20
+ if not client.shared:
21
+ client.connect_handlers.remove(on_client_connect) # type: ignore
22
+
23
+ ui.context.client.on_connect(on_client_connect)
24
+
25
+ def register(self, task: Callable[..., None]):
26
+ if ui.context.client.has_socket_connection:
27
+ task()
28
+ else:
29
+ self._tasks.append(task)
@@ -1,9 +1,6 @@
1
1
  from pathlib import Path
2
2
  from typing import Any, Callable, Dict, List, Union, cast, Optional
3
- from typing_extensions import Literal
4
3
  from ex4nicegui.reactive.utils import ParameterClassifier
5
- from ex4nicegui.utils.signals import on
6
-
7
4
  from ex4nicegui.utils.signals import (
8
5
  ReadonlyRef,
9
6
  is_ref,
@@ -11,28 +8,16 @@ from ex4nicegui.utils.signals import (
11
8
  _TMaybeRef as TMaybeRef,
12
9
  to_value,
13
10
  to_raw,
11
+ on,
14
12
  )
15
13
  from .base import BindableUi
16
- from ex4nicegui.reactive.EChartsComponent.ECharts import (
17
- echarts,
18
- EChartsMouseEventArguments,
19
- )
14
+ from ex4nicegui.reactive.EChartsComponent.ECharts import echarts
15
+ from ex4nicegui.reactive.EChartsComponent.types import _T_event_name
16
+ from ex4nicegui.reactive.EChartsComponent.events import EChartsMouseEventArguments
20
17
 
21
18
  from nicegui.awaitable_response import AwaitableResponse
22
19
  from nicegui import ui, app
23
20
 
24
- _TEventName = Literal[
25
- "click",
26
- "dblclick",
27
- "mousedown",
28
- "mousemove",
29
- "mouseup",
30
- "mouseover",
31
- "mouseout",
32
- "globalout",
33
- "contextmenu",
34
- ]
35
-
36
21
 
37
22
  class EChartsBindableUi(BindableUi[echarts]):
38
23
  EChartsMouseEventArguments = EChartsMouseEventArguments
@@ -50,6 +35,7 @@ class EChartsBindableUi(BindableUi[echarts]):
50
35
  value_kws = pc.get_values_kws()
51
36
 
52
37
  element = echarts(**value_kws).classes("grow self-stretch h-[16rem]")
38
+
53
39
  super().__init__(element) # type: ignore
54
40
 
55
41
  self.__update_setting = None
@@ -78,17 +64,17 @@ class EChartsBindableUi(BindableUi[echarts]):
78
64
  ui.add_body_html(
79
65
  rf"""
80
66
  <script>
81
- window.addEventListener('DOMContentLoaded', () => {{
82
- fetch("{src}")
83
- .then((response) => response.json())
84
- .then((data) => {{
85
- echarts.registerMap('{map_name}', data);
86
- }});
87
- }});
67
+ if (typeof window.ex4ngEchartsMapTasks === "undefined") {{
68
+ window.ex4ngEchartsMapTasks = new Map();
69
+ }}
70
+
71
+ window.ex4ngEchartsMapTasks.set('{map_name}', '{src}');
88
72
  </script>
89
73
  """
90
74
  )
91
75
 
76
+ return cls
77
+
92
78
  @classmethod
93
79
  def from_pyecharts(cls, chart: TMaybeRef):
94
80
  if is_ref(chart):
@@ -147,7 +133,7 @@ class EChartsBindableUi(BindableUi[echarts]):
147
133
 
148
134
  def on(
149
135
  self,
150
- event_name: _TEventName,
136
+ event_name: _T_event_name,
151
137
  handler: Callable[..., Any],
152
138
  query: Optional[Union[str, Dict]] = None,
153
139
  ):
@@ -224,6 +210,7 @@ class EChartsBindableUi(BindableUi[echarts]):
224
210
  ---
225
211
  """
226
212
  self.element.echarts_on(event_name, handler, query)
213
+ return self
227
214
 
228
215
  def run_chart_method(
229
216
  self, name: str, *args, timeout: float = 1, check_interval: float = 0.01
@@ -4,6 +4,7 @@ from typing import (
4
4
  Optional,
5
5
  TypeVar,
6
6
  Dict,
7
+ Union,
7
8
  )
8
9
  from ex4nicegui.reactive.utils import ParameterClassifier
9
10
  from ex4nicegui.utils.apiEffect import ui_effect
@@ -25,7 +26,7 @@ class NumberBindableUi(BindableUi[ui.number]):
25
26
  label: Optional[TMaybeRef[str]] = None,
26
27
  *,
27
28
  placeholder: Optional[TMaybeRef[str]] = None,
28
- value: Optional[TMaybeRef[float]] = None,
29
+ value: Optional[Union[TMaybeRef[float], TMaybeRef[int]]] = None,
29
30
  min: Optional[TMaybeRef[float]] = None,
30
31
  max: Optional[TMaybeRef[float]] = None,
31
32
  step: Optional[TMaybeRef[float]] = None,
@@ -2,7 +2,6 @@ from typing import Dict
2
2
  from signe.core.scope import ScopeSuite
3
3
  from nicegui import Client, ui
4
4
 
5
-
6
5
  _TClientID = str
7
6
 
8
7
 
@@ -18,12 +17,18 @@ class NgClientScopeManager:
18
17
  self._client_scope_map: Dict[_TClientID, NgScopeSuite] = {}
19
18
 
20
19
  def new_scope(self, detached: bool = False):
21
- return self.get_current_scope().scope(detached)
20
+ """Create a scope that can collect all reactive watch functions within it, allowing for a unified destruction process.
22
21
 
23
- def get_current_scope(self):
24
- # if len(ng_context.get_slot_stack()) <= 0:
25
- # return
22
+ @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#new_scope
23
+ @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#new_scope
24
+
25
+ Args:
26
+ detached (bool, optional): Whether the scope should be detached from the client. Defaults to False.
27
+
28
+ """
29
+ return self.get_current_scope().scope(detached=detached)
26
30
 
31
+ def get_current_scope(self):
27
32
  client = ui.context.client
28
33
 
29
34
  if client.id not in self._client_scope_map:
@@ -35,10 +40,13 @@ class NgClientScopeManager:
35
40
  @client.on_disconnect
36
41
  def _(e: Client):
37
42
  if e.id in self._client_scope_map:
38
- self._client_scope_map[e.id]._top_scope.dispose()
43
+ self._client_scope_map[e.id]._top_scope.dispose() # type: ignore
39
44
  del self._client_scope_map[e.id]
40
45
 
41
46
  return self._client_scope_map[client.id]
42
47
 
43
48
 
44
49
  _CLIENT_SCOPE_MANAGER = NgClientScopeManager()
50
+
51
+
52
+ new_scope = _CLIENT_SCOPE_MANAGER.new_scope
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ex4nicegui
3
- Version: 0.6.5
3
+ Version: 0.6.6
4
4
  Summary: Extension library based on nicegui, providing data responsive,BI functionality modules
5
5
  Home-page:
6
6
  Author: carson_jia
@@ -424,6 +424,31 @@ ui.button("change b", on_click=change_b)
424
424
 
425
425
  ---
426
426
 
427
+ ### `new_scope`
428
+
429
+ By default, all watch functions are automatically destroyed when the client connection is disconnected. For finer-grained control, the `new_scope` function can be utilized.
430
+
431
+ ```python
432
+ from nicegui import ui
433
+ from ex4nicegui import rxui, to_ref, effect, new_scope
434
+
435
+ a = to_ref(0.0)
436
+
437
+ scope1 = new_scope()
438
+
439
+ @scope1.run
440
+ def _():
441
+ @effect
442
+ def _():
443
+ print(f"scope 1:{a.value}")
444
+
445
+
446
+ rxui.number(value=a)
447
+ rxui.button("dispose scope 1", on_click=scope1.dispose)
448
+ ```
449
+
450
+ ---
451
+
427
452
  ## functionality
428
453
 
429
454
  ### vmodel
@@ -1,4 +1,4 @@
1
- ex4nicegui/__init__.py,sha256=-00dmxm2M188iPRftlKHd-mU6A-FbezqyyvVluNDaD8,818
1
+ ex4nicegui/__init__.py,sha256=NxkjzifbZg-o2hX4ENk1ekPacAnu1PLi7dr34QsomEw,886
2
2
  ex4nicegui/bi/__init__.py,sha256=eu-2CuzzrcHCyKQOfoo87v6C9nSwFDdeLhjY0cRV13M,315
3
3
  ex4nicegui/bi/dataSource.py,sha256=hOOUN4PpSfPx4Vp1sg9Sfxi5K-wROw9C22Z-mmNXs6w,7644
4
4
  ex4nicegui/bi/dataSourceFacade.py,sha256=6NuAyrTIk_L2Tz9IRFpuHKRQY_OwJINDzxoM6JYOc14,8186
@@ -13,7 +13,7 @@ ex4nicegui/bi/elements/text.py,sha256=oX7S1cVQL6YGMOlQG_cdwK9duzOHCPG0lOi9qTZwo6
13
13
  ex4nicegui/bi/elements/ui_aggrid.py,sha256=Lbtcmu_GR5_metQ9p8a2bzYSXsgElOZRMGl1h0fqcFU,2009
14
14
  ex4nicegui/bi/elements/ui_date_picker.js,sha256=Tk6NACKVsCnqhWZtuNA6Xt2e-AWI54AnjfHPIldaM5A,852
15
15
  ex4nicegui/bi/elements/ui_date_picker.py,sha256=PGv8gsgc4hkvWa-EN19qznEllV7DAzz7v4aTwdx9do4,2260
16
- ex4nicegui/bi/elements/ui_echarts.py,sha256=o_wIqxyrU27UvTSIRp6_58nQSic9llh1CuHI9QcRMOc,2302
16
+ ex4nicegui/bi/elements/ui_echarts.py,sha256=B-YCMLzb4Wr3sQIMbtTZAoVXfPqTBvbZk-CU4vFBbBk,2248
17
17
  ex4nicegui/bi/elements/ui_radio.py,sha256=tIoBZVhoY-z3dhGxh2pYENuxVnwkHhZB5g4_a5QPMRE,5447
18
18
  ex4nicegui/bi/elements/ui_range.py,sha256=1tnka-a0jVfqTwvypKIRgHb6EzYGn3DmsWr3yvSVD-g,4128
19
19
  ex4nicegui/bi/elements/ui_select.py,sha256=yOab3YrHCZ5kkU3bmDdr-LIAMhOunUsCbtctR8WpnLI,3872
@@ -67,6 +67,7 @@ ex4nicegui/libs/gsap/utils/matrix.js,sha256=77scrxbQZXx4ex5HkvnT9IkhMG1rQoDNp4TS
67
67
  ex4nicegui/libs/gsap/utils/paths.js,sha256=2SPaRHQ7zgba9cH8hGhkTYPCZdrrEhE2qhh6ECAEvSA,49314
68
68
  ex4nicegui/libs/gsap/utils/strings.js,sha256=47G9slz5ltG9mDSwrfQDtWzzdV5QJ-AIMLRMNK0VSiM,10472
69
69
  ex4nicegui/reactive/__init__.py,sha256=-FC9JUa7bMqozkbbKlpWJB7WY8HuojAINgAD8ZcxHdY,3714
70
+ ex4nicegui/reactive/deferredTask.py,sha256=l__Qdis24jAO97_DSHW1yBns0f13-OK02O2SSkyvoZQ,824
70
71
  ex4nicegui/reactive/empty.js,sha256=Y-caS4CN8jUq59LgGgcvgfkndze-RgWF_ZMmAcxOrbw,50
71
72
  ex4nicegui/reactive/empty.py,sha256=kB851B12V1_VCNsFKW6OmjcdIiuZqGEGjLgA6k6yug8,132
72
73
  ex4nicegui/reactive/fileWatcher.py,sha256=gjeZhgar02f-qGQa47Tj5SMaCP_ftRtSU898XUmXl1U,1472
@@ -80,9 +81,12 @@ ex4nicegui/reactive/utils.py,sha256=DZ77y0qQAeHUb52yyCKlLE5_3MQlE_OAUH_M1s31_Qg,
80
81
  ex4nicegui/reactive/vfor.js,sha256=xtKVUPSN0BP99H0BO6LRUYFqxqTGIRttQh5UjoUTwBc,282
81
82
  ex4nicegui/reactive/vfor.py,sha256=LntYIilx3JoeGjplRKLgW9cxzX9uRw27n6YRF9ROxN8,5778
82
83
  ex4nicegui/reactive/vmodel.py,sha256=SgmchPVfM6uQAH60VlVyNobfuTg3ScuxlXNFJLRD-r8,5091
83
- ex4nicegui/reactive/EChartsComponent/ECharts.js,sha256=HMmgXlDl548H4JpozDSbLWv-opvPi3OdJz_XY_MHbnY,3326
84
- ex4nicegui/reactive/EChartsComponent/ECharts.py,sha256=PbRChy9bgJndizyahDUxaV8LYN7sGH_A8licXA2DAC8,6313
84
+ ex4nicegui/reactive/EChartsComponent/ECharts.js,sha256=TA7a4NXWJOo7WrLLiA_TUFvgVygVHVQBQ2mE2m193F4,3164
85
+ ex4nicegui/reactive/EChartsComponent/ECharts.py,sha256=ho6Cnz5zv99UXyQGdoln81KSCWlLsA4ZUT0Jdic4Xmo,4490
85
86
  ex4nicegui/reactive/EChartsComponent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
+ ex4nicegui/reactive/EChartsComponent/events.py,sha256=_BtmLRcAIZciDQT5i1eFc-r3e0pBnAabW1BSl6uzhCc,570
88
+ ex4nicegui/reactive/EChartsComponent/types.py,sha256=_7AekG0IyzRpDEBZMtKRiZ3o3dUCcn6btegBk8c9Fig,1001
89
+ ex4nicegui/reactive/EChartsComponent/utils.py,sha256=a5r2fghC6IIZbyfUUR8TEkpLj9HPbcf8QHEBatXaL2M,1463
86
90
  ex4nicegui/reactive/UseDraggable/UseDraggable.js,sha256=xZm_g_L2lamxAjiAeGPDR0CNmjlvgzuiJ6gH77pNrg4,5473
87
91
  ex4nicegui/reactive/UseDraggable/UseDraggable.py,sha256=Zh6NfQPSf3nMvCL8wDA4tjhyH7jfqt9cnbJ7L4cI-SU,3929
88
92
  ex4nicegui/reactive/UseDraggable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -103,7 +107,7 @@ ex4nicegui/reactive/officials/color_picker.py,sha256=fSRICdzdH16w3BIGyAk3CtaauYq
103
107
  ex4nicegui/reactive/officials/column.py,sha256=CfoJigEdpRoGaJTY_O7wbK8cp8ufX8mYUKNRUnPWUr0,1040
104
108
  ex4nicegui/reactive/officials/date.py,sha256=jp75WgZaICnCHLS_wpF3uJI2kaGeNqmRLj3qpn5IIyg,2681
105
109
  ex4nicegui/reactive/officials/drawer.py,sha256=y9_gbDDy_6Y7mRfSB8BGawM-_g6kECM1ieZXMX2YCQo,2370
106
- ex4nicegui/reactive/officials/echarts.py,sha256=btLYAqYuWv_zlX3KJH-L_rofx8HblYbscnVDf-bz23w,9696
110
+ ex4nicegui/reactive/officials/echarts.py,sha256=QCpShx9Gy-0kriSPXb4CFNHhSlfjtXjIQVNTk8juXes,9495
107
111
  ex4nicegui/reactive/officials/element.py,sha256=-qsHcxfF3fMfU0sJlKtTksX_wYPMIPJ_AgFcZbbI754,412
108
112
  ex4nicegui/reactive/officials/expansion.py,sha256=pAFGaj_N88KLNPw2476lthyZbCOa3APlMtHsgRT9rWI,1873
109
113
  ex4nicegui/reactive/officials/grid.py,sha256=z3mdvDnpxKECtvioTgGXROc1kcAugNCBOvwZ7NCpQHI,865
@@ -115,7 +119,7 @@ ex4nicegui/reactive/officials/input.py,sha256=d338LH7tYArhUQYXJleytIOXsDieXEm4yL
115
119
  ex4nicegui/reactive/officials/knob.py,sha256=ZCKXUbFQUhdsRoTADk2gqdEwmi1CeW9Jmc7AGJyV1Yg,2153
116
120
  ex4nicegui/reactive/officials/label.py,sha256=7xhvQIa-3Zm44xJIoKeMys1M6d6AMJTeE5l9THPICGo,1398
117
121
  ex4nicegui/reactive/officials/linear_progress.py,sha256=3ew4uqUIDrDH0PdX42K7rnKQL4khmZgxmJfmWX6qMDs,2128
118
- ex4nicegui/reactive/officials/number.py,sha256=Ro20LiSjzeLkcPM5oIe3phulLH5Gsw3YwYBCyRl9bqI,2201
122
+ ex4nicegui/reactive/officials/number.py,sha256=Ndzjbo9eilNd-pfOLqpB4RVlUNXoMHnfyO_b7Jbdx4Q,2236
119
123
  ex4nicegui/reactive/officials/radio.py,sha256=35KCAE0JhzBczaCGrlufZystgpzljobOoIw1H7js1KA,1929
120
124
  ex4nicegui/reactive/officials/row.py,sha256=pwFJBdv3_D5-E-oga-OG5t57ahHcYXGSI_-UofWg_j0,1029
121
125
  ex4nicegui/reactive/officials/select.py,sha256=Fj4V96ju2tpsP1ok0RFokN1K7TxzNS9YLVCz55O788Y,2980
@@ -137,13 +141,13 @@ ex4nicegui/tools/debug.py,sha256=h9iYHxw7jWWvmiExSpGi2hQl1PfhPZgC2KNS_GTuHSw,486
137
141
  ex4nicegui/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
142
  ex4nicegui/utils/apiEffect.py,sha256=tAvQ-6sbSbZBZ1bibdAdQNb_BjrUF1uALwOkAdV_Y8M,2527
139
143
  ex4nicegui/utils/asyncComputed.py,sha256=-v19ic20URewLkjbms5Teco1k8LPRnpP7usjrgo1pRU,1505
140
- ex4nicegui/utils/clientScope.py,sha256=ekS3thfir7iQ1L3wHbe4gJ3FhQjRcM3PLn6QCJ8wDNw,1267
144
+ ex4nicegui/utils/clientScope.py,sha256=AM5GQLXSIrLALnzz72ZmplykhKVhRjRxQdHdAeR7g7k,1719
141
145
  ex4nicegui/utils/common.py,sha256=7P0vboDadLun6EMxNi3br9rKJgKt0QT4sy_66cHEwb4,994
142
146
  ex4nicegui/utils/effect.py,sha256=MgvWuAP3OFs2bR4ef6uXPwGCkKORUK-4hmx1oSwl04Y,2310
143
147
  ex4nicegui/utils/scheduler.py,sha256=Wa963Df3UDvWHjXXoVYGIBevIILzCFoz-yAWjvxeyfQ,1218
144
148
  ex4nicegui/utils/signals.py,sha256=-80iaAzIyUDR_7LBr8TfOY59Fj4dSq92klWXoRy538g,11346
145
- ex4nicegui-0.6.5.dist-info/LICENSE,sha256=0KDDElS2dl-HIsWvbpy8ywbLzJMBFzXLev57LnMIZXs,1094
146
- ex4nicegui-0.6.5.dist-info/METADATA,sha256=jhr7cj9AuuCJdsuZZRSoHb7Fw9vgbYLAMivi7kNHYzs,27619
147
- ex4nicegui-0.6.5.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
148
- ex4nicegui-0.6.5.dist-info/top_level.txt,sha256=VFwMiO9AFjj5rfLMJwN1ipLRASk9fJXB8tM6DNrpvPQ,11
149
- ex4nicegui-0.6.5.dist-info/RECORD,,
149
+ ex4nicegui-0.6.6.dist-info/LICENSE,sha256=0KDDElS2dl-HIsWvbpy8ywbLzJMBFzXLev57LnMIZXs,1094
150
+ ex4nicegui-0.6.6.dist-info/METADATA,sha256=J896pvPcnLUqNJMZ_xk2lf92TsPqsEjW7Ot68ouz770,28134
151
+ ex4nicegui-0.6.6.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
152
+ ex4nicegui-0.6.6.dist-info/top_level.txt,sha256=VFwMiO9AFjj5rfLMJwN1ipLRASk9fJXB8tM6DNrpvPQ,11
153
+ ex4nicegui-0.6.6.dist-info/RECORD,,