nodekit 0.2.0__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.
Files changed (62) hide show
  1. nodekit/.DS_Store +0 -0
  2. nodekit/__init__.py +53 -0
  3. nodekit/_internal/__init__.py +0 -0
  4. nodekit/_internal/ops/__init__.py +0 -0
  5. nodekit/_internal/ops/build_site/__init__.py +117 -0
  6. nodekit/_internal/ops/build_site/harness.j2 +158 -0
  7. nodekit/_internal/ops/concat.py +51 -0
  8. nodekit/_internal/ops/open_asset_save_asset.py +125 -0
  9. nodekit/_internal/ops/play/__init__.py +4 -0
  10. nodekit/_internal/ops/play/local_runner/__init__.py +0 -0
  11. nodekit/_internal/ops/play/local_runner/main.py +234 -0
  12. nodekit/_internal/ops/play/local_runner/site-template.j2 +38 -0
  13. nodekit/_internal/ops/save_graph_load_graph.py +131 -0
  14. nodekit/_internal/ops/topological_sorting.py +122 -0
  15. nodekit/_internal/types/__init__.py +0 -0
  16. nodekit/_internal/types/actions/__init__.py +0 -0
  17. nodekit/_internal/types/actions/actions.py +89 -0
  18. nodekit/_internal/types/assets/__init__.py +151 -0
  19. nodekit/_internal/types/cards/__init__.py +85 -0
  20. nodekit/_internal/types/events/__init__.py +0 -0
  21. nodekit/_internal/types/events/events.py +145 -0
  22. nodekit/_internal/types/expressions/__init__.py +0 -0
  23. nodekit/_internal/types/expressions/expressions.py +242 -0
  24. nodekit/_internal/types/graph.py +42 -0
  25. nodekit/_internal/types/node.py +21 -0
  26. nodekit/_internal/types/regions/__init__.py +13 -0
  27. nodekit/_internal/types/sensors/__init__.py +0 -0
  28. nodekit/_internal/types/sensors/sensors.py +156 -0
  29. nodekit/_internal/types/trace.py +17 -0
  30. nodekit/_internal/types/transition.py +68 -0
  31. nodekit/_internal/types/value.py +145 -0
  32. nodekit/_internal/utils/__init__.py +0 -0
  33. nodekit/_internal/utils/get_browser_bundle.py +35 -0
  34. nodekit/_internal/utils/get_extension_from_media_type.py +15 -0
  35. nodekit/_internal/utils/hashing.py +46 -0
  36. nodekit/_internal/utils/iter_assets.py +61 -0
  37. nodekit/_internal/version.py +1 -0
  38. nodekit/_static/nodekit.css +10 -0
  39. nodekit/_static/nodekit.js +59 -0
  40. nodekit/actions/__init__.py +25 -0
  41. nodekit/assets/__init__.py +7 -0
  42. nodekit/cards/__init__.py +15 -0
  43. nodekit/events/__init__.py +30 -0
  44. nodekit/experimental/.DS_Store +0 -0
  45. nodekit/experimental/__init__.py +0 -0
  46. nodekit/experimental/recruitment_services/__init__.py +0 -0
  47. nodekit/experimental/recruitment_services/base.py +77 -0
  48. nodekit/experimental/recruitment_services/mechanical_turk/__init__.py +0 -0
  49. nodekit/experimental/recruitment_services/mechanical_turk/client.py +359 -0
  50. nodekit/experimental/recruitment_services/mechanical_turk/models.py +116 -0
  51. nodekit/experimental/s3.py +219 -0
  52. nodekit/experimental/turk_helper.py +223 -0
  53. nodekit/experimental/visualization/.DS_Store +0 -0
  54. nodekit/experimental/visualization/__init__.py +0 -0
  55. nodekit/experimental/visualization/pointer.py +443 -0
  56. nodekit/expressions/__init__.py +55 -0
  57. nodekit/sensors/__init__.py +25 -0
  58. nodekit/transitions/__init__.py +15 -0
  59. nodekit/values/__init__.py +63 -0
  60. nodekit-0.2.0.dist-info/METADATA +221 -0
  61. nodekit-0.2.0.dist-info/RECORD +62 -0
  62. nodekit-0.2.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,443 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Tuple, List
4
+
5
+ import matplotlib
6
+ import numpy as np
7
+
8
+ from nodekit.events import PointerSampledEvent
9
+
10
+ # import matplotlib
11
+ matplotlib.use("Agg") # safe for headless render
12
+ import matplotlib.pyplot as plt
13
+ from matplotlib import animation
14
+ from matplotlib.colors import to_rgba
15
+
16
+ from typing import Dict
17
+
18
+
19
+ def make_animation(
20
+ events: Dict[str, List[PointerSampledEvent]], # trace_id -> event stream
21
+ savepath: os.PathLike | str,
22
+ accent_rgba: Tuple[float, float, float, float]
23
+ | Dict[str, Tuple[float, float, float, float]] = (
24
+ 49 / 255,
25
+ 124 / 255,
26
+ 245 / 255,
27
+ 0.9,
28
+ ),
29
+ neutral_rgba: Tuple[float, float, float, float]
30
+ | Dict[str, Tuple[float, float, float, float]] = (0.1, 0.1, 0.1, 0.3),
31
+ movie_size_px: int = 500,
32
+ movie_time_sec: int = 10,
33
+ ):
34
+ """
35
+ Render multiple pointer streams in a single transparent .mov.
36
+
37
+ Visual semantics (per trace):
38
+ - MOVE: no dots (only influences trails).
39
+ - DOWN/UP: accent-colored dots; alpha and (UP) size decay over time.
40
+ - Persistent trail: single path from start → 'now'; ALWAYS neutral color; no fade; 1/2 width.
41
+ - Following trail: single segment from previous sample → time-interpolated point toward next sample;
42
+ ALWAYS neutral color; fades with the move tau.
43
+
44
+ Z-index:
45
+ - Traces are layered by insertion order of `events` (earlier keys are below later keys),
46
+ and this order is fixed for the whole movie. Within each trace: persistent trail (lowest),
47
+ then following trail, then DOWN/UP dots (highest).
48
+
49
+ Coordinates:
50
+ - Input x,y in (-0.5, 0.5), right is +x, up is +y. Output is a square of size movie_size_px.
51
+
52
+ Timing:
53
+ - 60 fps, length = movie_time_sec. Samples outside [0, movie_time_sec*1000) ms are ignored.
54
+ """
55
+
56
+ # ----------------------------
57
+ # Params & scaling
58
+ # ----------------------------
59
+ scale = movie_size_px / 768.0 # baseline-normalized scaling
60
+
61
+ fps = 60
62
+ T_ms = int(movie_time_sec * 1000)
63
+
64
+ # Decays (alpha ~ exp(-dt / tau))
65
+ tau_alpha_ms_move = 500.0
66
+ tau_alpha_ms_down = 700.0
67
+ tau_alpha_ms_up = 600.0
68
+ tau_size_ms_up = tau_alpha_ms_up
69
+
70
+ # Sizes (scatter 's' is points^2)
71
+ down_size0 = 90.0 * scale**2
72
+ up_size0 = 400.0 * scale**2
73
+
74
+ # Line widths
75
+ linewidth_follow = 10.0 * scale # following trail
76
+ linewidth_persist = 0.25 * linewidth_follow # persistent trail
77
+
78
+ # Tail window for DOWN/UP visibility
79
+ tail_window_ms = int(6 * max(tau_alpha_ms_move, tau_alpha_ms_down, tau_alpha_ms_up))
80
+
81
+ # ----------------------------
82
+ # Normalize & validate color specs
83
+ # ----------------------------
84
+ trace_ids = list(events.keys()) # insertion order retained
85
+
86
+ def _normalize_color_spec(
87
+ spec, name: str
88
+ ) -> Dict[str, Tuple[float, float, float, float]]:
89
+ if isinstance(spec, dict):
90
+ missing = set(trace_ids) - set(spec.keys())
91
+ extra = set(spec.keys()) - set(trace_ids)
92
+ if missing or extra:
93
+ raise ValueError(
94
+ f"{name} dict must enumerate exactly all traces. "
95
+ f"Missing: {sorted(missing)}; Extra: {sorted(extra)}"
96
+ )
97
+ return {k: to_rgba(v) for k, v in spec.items()}
98
+ else:
99
+ rgba = to_rgba(spec)
100
+ return {k: rgba for k in trace_ids}
101
+
102
+ per_trace_accent = _normalize_color_spec(accent_rgba, "accent_rgba")
103
+ per_trace_neutral = _normalize_color_spec(neutral_rgba, "neutral_rgba")
104
+
105
+ # ----------------------------
106
+ # Preprocess per-trace arrays (sorted, filtered to movie window)
107
+ # ----------------------------
108
+ streams = [] # list of dicts, in z-order
109
+ for tid in trace_ids:
110
+ ev = [e for e in events[tid] if 0 <= e.t < T_ms]
111
+ if not ev:
112
+ # still create an empty stream so z-ordering remains consistent
113
+ streams.append(
114
+ dict(
115
+ trace_id=tid,
116
+ kinds=np.array([], dtype=object),
117
+ xs=np.array([], dtype=float),
118
+ ys=np.array([], dtype=float),
119
+ ts=np.array([], dtype=int),
120
+ is_down=np.array([], dtype=bool),
121
+ is_up=np.array([], dtype=bool),
122
+ accent=per_trace_accent[tid],
123
+ neutral=per_trace_neutral[tid],
124
+ )
125
+ )
126
+ continue
127
+
128
+ ev.sort(key=lambda e: e.t)
129
+
130
+ kinds = np.array([e.kind for e in ev], dtype=object)
131
+ xs = np.array([e.x for e in ev], dtype=float)
132
+ ys = np.array([e.y for e in ev], dtype=float)
133
+ ts = np.array([e.t for e in ev], dtype=int)
134
+
135
+ is_down = kinds == "down"
136
+ is_up = kinds == "up"
137
+
138
+ streams.append(
139
+ dict(
140
+ trace_id=tid,
141
+ kinds=kinds,
142
+ xs=xs,
143
+ ys=ys,
144
+ ts=ts,
145
+ is_down=is_down,
146
+ is_up=is_up,
147
+ accent=per_trace_accent[tid],
148
+ neutral=per_trace_neutral[tid],
149
+ )
150
+ )
151
+
152
+ # ----------------------------
153
+ # Figure/axes
154
+ # ----------------------------
155
+ dpi = 100
156
+ fig_inch = movie_size_px / dpi
157
+ fig = plt.figure(figsize=(fig_inch, fig_inch), dpi=dpi)
158
+ ax = plt.axes((0, 0, 1, 1))
159
+ ax.set_xlim(-0.5, 0.5)
160
+ ax.set_ylim(-0.5, 0.5)
161
+ ax.set_aspect("equal", adjustable="box")
162
+
163
+ fig.patch.set_alpha(0.0)
164
+ ax.set_facecolor((0, 0, 0, 0))
165
+ for spine in ax.spines.values():
166
+ spine.set_visible(False)
167
+ ax.set_xticks([])
168
+ ax.set_yticks([])
169
+
170
+ # ----------------------------
171
+ # Artists per trace in insertion order (controls z-index)
172
+ # ----------------------------
173
+ # Within each trace: persistent (lowest), following, points (highest)
174
+ trace_artists = []
175
+ for z, S in enumerate(streams):
176
+ base_z = z * 3 # reserve 3 zorders per trace
177
+ # persistent neutral path
178
+ (persist_line,) = ax.plot(
179
+ [],
180
+ [],
181
+ linewidth=linewidth_persist,
182
+ solid_capstyle="round",
183
+ solid_joinstyle="round",
184
+ zorder=base_z + 0,
185
+ )
186
+ persist_line.set_color(S["neutral"])
187
+
188
+ # following neutral segment (fading)
189
+ (follow_line,) = ax.plot(
190
+ [],
191
+ [],
192
+ linewidth=linewidth_follow,
193
+ solid_capstyle="round",
194
+ solid_joinstyle="round",
195
+ zorder=base_z + 1,
196
+ )
197
+ follow_line.set_color((S["neutral"][0], S["neutral"][1], S["neutral"][2], 0.0))
198
+
199
+ # DOWN/UP scatter only
200
+ scatter = ax.scatter(
201
+ [], [], s=[], facecolors=[], edgecolors="none", zorder=base_z + 2
202
+ )
203
+
204
+ trace_artists.append(
205
+ dict(scatter=scatter, persist=persist_line, follow=follow_line, stream=S)
206
+ )
207
+
208
+ # ----------------------------
209
+ # Frames
210
+ # ----------------------------
211
+ num_frames = fps * movie_time_sec
212
+ frame_times = np.arange(num_frames, dtype=int) * int(1000 / fps)
213
+
214
+ def init():
215
+ for A in trace_artists:
216
+ A["scatter"].set_offsets(np.empty((0, 2)))
217
+ A["scatter"].set_sizes(np.empty((0,)))
218
+ A["scatter"].set_facecolors(np.empty((0, 4)))
219
+
220
+ A["persist"].set_data([], [])
221
+ # persist color already set per trace
222
+
223
+ A["follow"].set_data([], [])
224
+ n = A["stream"]["neutral"]
225
+ A["follow"].set_color((n[0], n[1], n[2], 0.0))
226
+
227
+ # return a flat tuple of all artists for blitting
228
+ out = []
229
+ for A in trace_artists:
230
+ out.extend([A["scatter"], A["persist"], A["follow"]])
231
+ return tuple(out)
232
+
233
+ def update(frame_idx: int):
234
+ t_now = int(frame_times[frame_idx])
235
+
236
+ drawn = []
237
+ for A in trace_artists:
238
+ S = A["stream"]
239
+ kinds, xs, ys, ts = S["kinds"], S["xs"], S["ys"], S["ts"]
240
+ accent, neutral = S["accent"], S["neutral"]
241
+
242
+ # --- DOWN/UP points within tail window ---
243
+ if ts.size == 0:
244
+ A["scatter"].set_offsets(np.empty((0, 2)))
245
+ A["scatter"].set_sizes(np.empty((0,)))
246
+ A["scatter"].set_facecolors(np.empty((0, 4)))
247
+ else:
248
+ t_min = max(0, t_now - tail_window_ms)
249
+ m = (ts >= t_min) & (ts <= t_now)
250
+ if not np.any(m):
251
+ A["scatter"].set_offsets(np.empty((0, 2)))
252
+ A["scatter"].set_sizes(np.empty((0,)))
253
+ A["scatter"].set_facecolors(np.empty((0, 4)))
254
+ else:
255
+ dt = (t_now - ts[m]).astype(float)
256
+ k = kinds[m]
257
+ xm = xs[m]
258
+ ym = ys[m]
259
+
260
+ down_mask = k == "down"
261
+ up_mask = k == "up"
262
+
263
+ alpha = np.zeros_like(dt, dtype=float)
264
+ alpha[down_mask] = np.exp(-dt[down_mask] / tau_alpha_ms_down)
265
+ alpha[up_mask] = np.exp(-dt[up_mask] / tau_alpha_ms_up)
266
+
267
+ size = np.zeros_like(dt, dtype=float)
268
+ size[down_mask] = down_size0
269
+ size[up_mask] = up_size0 * np.exp(-dt[up_mask] / tau_size_ms_up)
270
+ size = np.clip(size, 0.1, None)
271
+
272
+ keep = down_mask | up_mask
273
+ xm, ym, size, alpha_keep = (
274
+ xm[keep],
275
+ ym[keep],
276
+ size[keep],
277
+ alpha[keep],
278
+ )
279
+
280
+ colors = np.tile(accent, (len(alpha_keep), 1)).astype(float)
281
+ colors[:, 3] = np.clip(colors[:, 3] * alpha_keep, 0.0, 1.0)
282
+
283
+ if xm.size == 0:
284
+ A["scatter"].set_offsets(np.empty((0, 2)))
285
+ A["scatter"].set_sizes(np.empty((0,)))
286
+ A["scatter"].set_facecolors(np.empty((0, 4)))
287
+ else:
288
+ A["scatter"].set_offsets(np.column_stack([xm, ym]))
289
+ A["scatter"].set_sizes(size)
290
+ A["scatter"].set_facecolors(colors)
291
+
292
+ # --- Persistent trail: single path up to now (neutral, no fade) ---
293
+ if ts.size >= 1:
294
+ vx, vy = [], []
295
+ for i in range(ts.size):
296
+ if ts[i] > t_now:
297
+ break
298
+ if i == ts.size - 1:
299
+ vx.append(xs[i])
300
+ vy.append(ys[i])
301
+ else:
302
+ t0, t1 = ts[i], ts[i + 1]
303
+ x0, y0 = xs[i], ys[i]
304
+ x1, y1 = xs[i + 1], ys[i + 1]
305
+ vx.append(x0)
306
+ vy.append(y0)
307
+ if t0 <= t_now < t1:
308
+ frac = (t_now - t0) / (t1 - t0)
309
+ vx.append(x0 + frac * (x1 - x0))
310
+ vy.append(y0 + frac * (y1 - y0))
311
+ break
312
+ else:
313
+ vx.append(x1)
314
+ vy.append(y1)
315
+
316
+ if len(vx) >= 2:
317
+ A["persist"].set_data(vx, vy)
318
+ A["persist"].set_color(neutral)
319
+ else:
320
+ A["persist"].set_data([], [])
321
+ else:
322
+ A["persist"].set_data([], [])
323
+
324
+ # --- Following trail: single segment prev -> interpolated now (neutral, fades) ---
325
+ A["follow"].set_data([], [])
326
+ A["follow"].set_color((neutral[0], neutral[1], neutral[2], 0.0))
327
+ if ts.size >= 2:
328
+ idx_prev = np.searchsorted(ts, t_now, side="right") - 1
329
+ if (
330
+ 0 <= idx_prev < ts.size - 1
331
+ and ts[idx_prev] <= t_now < ts[idx_prev + 1]
332
+ ):
333
+ t0, t1 = ts[idx_prev], ts[idx_prev + 1]
334
+ x0, y0 = xs[idx_prev], ys[idx_prev]
335
+ x1, y1 = xs[idx_prev + 1], ys[idx_prev + 1]
336
+ frac = (t_now - t0) / (t1 - t0)
337
+ x_star = x0 + frac * (x1 - x0)
338
+ y_star = y0 + frac * (y1 - y0)
339
+
340
+ alpha_line = float(np.exp(-(t_now - t0) / float(tau_alpha_ms_move)))
341
+ rgba = (
342
+ neutral[0],
343
+ neutral[1],
344
+ neutral[2],
345
+ np.clip(neutral[3] * alpha_line, 0.0, 1.0),
346
+ )
347
+
348
+ A["follow"].set_data([x0, x_star], [y0, y_star])
349
+ A["follow"].set_color(rgba)
350
+
351
+ drawn.extend([A["scatter"], A["persist"], A["follow"]])
352
+
353
+ return tuple(drawn)
354
+
355
+ anim = animation.FuncAnimation(
356
+ fig,
357
+ update,
358
+ init_func=init,
359
+ frames=fps * movie_time_sec,
360
+ interval=1000 / fps,
361
+ blit=True,
362
+ )
363
+
364
+ # ----------------------------
365
+ # Save with transparent background
366
+ # ----------------------------
367
+ savepath = Path(savepath)
368
+ savepath.parent.mkdir(parents=True, exist_ok=True)
369
+ if savepath.suffix.lower() != ".mov":
370
+ savepath = savepath.with_suffix(".mov")
371
+
372
+ try:
373
+ writer = animation.FFMpegWriter(
374
+ fps=fps,
375
+ codec="prores_ks",
376
+ extra_args=[
377
+ "-pix_fmt",
378
+ "yuva444p10le",
379
+ "-profile:v",
380
+ "4444",
381
+ "-vendor",
382
+ "ap10",
383
+ "-bits_per_mb",
384
+ "8000",
385
+ ],
386
+ bitrate=-1,
387
+ )
388
+ anim.save(
389
+ str(savepath),
390
+ writer=writer,
391
+ dpi=dpi,
392
+ savefig_kwargs={"transparent": True, "facecolor": (0, 0, 0, 0)},
393
+ )
394
+ except Exception:
395
+ writer = animation.FFMpegWriter(
396
+ fps=fps,
397
+ codec="png",
398
+ extra_args=["-pix_fmt", "rgba"],
399
+ bitrate=-1,
400
+ )
401
+ anim.save(
402
+ str(savepath),
403
+ writer=writer,
404
+ dpi=dpi,
405
+ savefig_kwargs={"transparent": True, "facecolor": (0, 0, 0, 0)},
406
+ )
407
+
408
+ plt.close(fig)
409
+
410
+
411
+ # %%
412
+ if __name__ == "__main__":
413
+ import json
414
+
415
+ payload = json.loads(
416
+ Path("example_pointer_events.json").read_text()
417
+ ) # hit_id: List[PointerSampledEvent]
418
+ # payload = json.loads(Path('/Users/mjl/Library/Application Support/JetBrains/PyCharm2025.1/scratches/nodekit-turk/fitts-law-pointers-example_pointer_events.json').read_text()) # hit_id: List[PointerSampledEvent]
419
+ pointer_events = {
420
+ hit_id: [PointerSampledEvent.model_validate(ev) for ev in payload[hit_id]]
421
+ for hit_id in sorted(payload.keys())
422
+ }
423
+
424
+ # Get minimum time and left shift everything
425
+ max_t_grand = 0
426
+ for hit_id in pointer_events.keys():
427
+ min_t = min([ev.t for ev in pointer_events[hit_id]])
428
+ max_t = max([ev.t for ev in pointer_events[hit_id]])
429
+ if max_t > max_t_grand:
430
+ max_t_grand = max_t
431
+
432
+ for ev in pointer_events[hit_id]:
433
+ ev.t -= min_t
434
+
435
+ movie_time_sec = int(min(10, max_t_grand / 1000))
436
+ make_animation(
437
+ events=pointer_events,
438
+ accent_rgba=(49 / 255, 124 / 255, 245 / 255, 0.9),
439
+ neutral_rgba=(0.1, 0.1, 0.1, 0.3),
440
+ savepath="movie.mov",
441
+ movie_size_px=500,
442
+ movie_time_sec=movie_time_sec,
443
+ )
@@ -0,0 +1,55 @@
1
+ __all__ = [
2
+ "Reg",
3
+ "Local",
4
+ "LastAction",
5
+ "GetListItem",
6
+ "GetDictValue",
7
+ "Lit",
8
+ "If",
9
+ "Not",
10
+ "Or",
11
+ "And",
12
+ "Eq",
13
+ "Ne",
14
+ "Gt",
15
+ "Ge",
16
+ "Lt",
17
+ "Le",
18
+ "Add",
19
+ "Sub",
20
+ "Mul",
21
+ "Div",
22
+ "Slice",
23
+ "Map",
24
+ "Filter",
25
+ "Fold",
26
+ "Expression",
27
+ ]
28
+
29
+ from nodekit._internal.types.expressions.expressions import (
30
+ Reg,
31
+ Local,
32
+ LastAction,
33
+ GetListItem,
34
+ GetDictValue,
35
+ Lit,
36
+ If,
37
+ Not,
38
+ Or,
39
+ And,
40
+ Eq,
41
+ Ne,
42
+ Gt,
43
+ Ge,
44
+ Lt,
45
+ Le,
46
+ Add,
47
+ Sub,
48
+ Mul,
49
+ Div,
50
+ Slice,
51
+ Map,
52
+ Filter,
53
+ Fold,
54
+ Expression,
55
+ )
@@ -0,0 +1,25 @@
1
+ __all__ = [
2
+ "WaitSensor",
3
+ "ClickSensor",
4
+ "KeySensor",
5
+ "SelectSensor",
6
+ "MultiSelectSensor",
7
+ "SliderSensor",
8
+ "TextEntrySensor",
9
+ "ProductSensor",
10
+ "SumSensor",
11
+ "Sensor",
12
+ ]
13
+
14
+ from nodekit._internal.types.sensors.sensors import (
15
+ WaitSensor,
16
+ ClickSensor,
17
+ KeySensor,
18
+ SelectSensor,
19
+ MultiSelectSensor,
20
+ SliderSensor,
21
+ TextEntrySensor,
22
+ ProductSensor,
23
+ SumSensor,
24
+ Sensor,
25
+ )
@@ -0,0 +1,15 @@
1
+ __all__ = [
2
+ "Go",
3
+ "End",
4
+ "IfThenElse",
5
+ "Switch",
6
+ "Transition",
7
+ ]
8
+
9
+ from nodekit._internal.types.transition import (
10
+ Go,
11
+ End,
12
+ IfThenElse,
13
+ Switch,
14
+ Transition,
15
+ )
@@ -0,0 +1,63 @@
1
+ """Public value types and aliases used across NodeKit models."""
2
+
3
+ __all__ = [
4
+ "Value",
5
+ "Boolean",
6
+ "Integer",
7
+ "Float",
8
+ "String",
9
+ "List",
10
+ "Dict",
11
+ "LeafValue",
12
+ # Space
13
+ "SpatialSize",
14
+ "SpatialPoint",
15
+ "Mask",
16
+ # Time
17
+ "TimeElapsedMsec",
18
+ "TimeDurationMsec",
19
+ # Text
20
+ "MarkdownString",
21
+ "ColorHexString",
22
+ # Keyboard
23
+ "PressableKey",
24
+ # Assets
25
+ "SHA256",
26
+ "ImageMediaType",
27
+ "VideoMediaType",
28
+ "MediaType",
29
+ # Identifiers
30
+ "NodeId",
31
+ "RegisterId",
32
+ ]
33
+
34
+ from nodekit._internal.types.value import (
35
+ Value,
36
+ Boolean,
37
+ Integer,
38
+ Float,
39
+ String,
40
+ List,
41
+ Dict,
42
+ LeafValue,
43
+ # Space
44
+ SpatialSize,
45
+ SpatialPoint,
46
+ Mask,
47
+ # Time
48
+ TimeElapsedMsec,
49
+ TimeDurationMsec,
50
+ # Text
51
+ MarkdownString,
52
+ ColorHexString,
53
+ # Keyboard
54
+ PressableKey,
55
+ # Assets
56
+ SHA256,
57
+ ImageMediaType,
58
+ VideoMediaType,
59
+ MediaType,
60
+ # Identifiers
61
+ NodeId,
62
+ RegisterId,
63
+ )