voodoojs 0.11.2 → 0.12.1

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 (41) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-H2ZUEQWV.js → chunk-4M4ZXHNY.js} +84 -19
  3. package/dist/{chunk-UV5PMS7P.js → chunk-72PMUUMT.js} +4 -4
  4. package/dist/{chunk-KQYSJHZR.js → chunk-AFMCDNYS.js} +5 -5
  5. package/dist/{chunk-DJJB35SR.js → chunk-D7675IJG.js} +6 -6
  6. package/dist/{chunk-IS3DR2KY.js → chunk-GXPNWCGE.js} +3 -3
  7. package/dist/{chunk-DCE5WIGA.js → chunk-HNM3CTBD.js} +5 -5
  8. package/dist/{chunk-IGZSDZKU.js → chunk-KN7NAKBL.js} +4 -4
  9. package/dist/{chunk-WJP3YGUI.js → chunk-LLNDLLKV.js} +4 -4
  10. package/dist/{chunk-V3O3WOZH.js → chunk-NP66JM2P.js} +4 -4
  11. package/dist/{chunk-AH2VXDZD.js → chunk-RDHYPGH6.js} +187 -18
  12. package/dist/{chunk-NFDXVIII.js → chunk-T5ION5NG.js} +3 -3
  13. package/dist/essential.cjs +263 -25
  14. package/dist/essential.d.cts +1 -1
  15. package/dist/essential.d.ts +1 -1
  16. package/dist/essential.js +10 -10
  17. package/dist/gpu.cjs +1 -1
  18. package/dist/gpu.js +10 -10
  19. package/dist/http.cjs +1 -1
  20. package/dist/http.js +5 -5
  21. package/dist/index.cjs +273 -27
  22. package/dist/index.d.cts +88 -4
  23. package/dist/index.d.ts +88 -4
  24. package/dist/index.js +20 -20
  25. package/dist/{query-Cf-7iibE.d.ts → query-DzHfm8Kg.d.ts} +40 -29
  26. package/dist/{query-DiQAS73Q.d.cts → query-XooOh4vB.d.cts} +40 -29
  27. package/dist/reactivity.cjs +1 -1
  28. package/dist/reactivity.js +2 -2
  29. package/dist/socket.cjs +1 -1
  30. package/dist/socket.js +9 -9
  31. package/dist/style-GR4X6O7I.js +5 -0
  32. package/dist/utils.cjs +1 -1
  33. package/dist/utils.js +2 -2
  34. package/dist/voodoo.core.js +242 -24
  35. package/dist/voodoo.core.min.js +17 -17
  36. package/dist/voodoo.full.js +266 -27
  37. package/dist/voodoo.full.min.js +57 -53
  38. package/dist/voodoo.js +264 -25
  39. package/dist/voodoo.min.js +29 -25
  40. package/package.json +1 -1
  41. package/dist/style-4X62SABN.js +0 -5
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Voodoo.js v0.11.2
2
+ * Voodoo.js v0.12.1
3
3
  * JavaScript feels like magic.
4
4
  * (c) 2026 Voodoo.js contributors. MIT License.
5
5
  */
@@ -2263,6 +2263,10 @@ Expression: ${expression}` : message);
2263
2263
  function magic(name, getter) {
2264
2264
  magics.set(name.startsWith("$") ? name : `$${name}`, getter);
2265
2265
  }
2266
+ var hooks = /* @__PURE__ */ new Map();
2267
+ function hook(name, getter) {
2268
+ hooks.set(name, getter);
2269
+ }
2266
2270
  var Scope = class _Scope {
2267
2271
  // Assignment order matches the order the fields were declared in before, so
2268
2272
  // the properties are created in the same sequence they always were.
@@ -2318,7 +2322,10 @@ Expression: ${expression}` : message);
2318
2322
  s = s.parent;
2319
2323
  }
2320
2324
  if (name.charCodeAt(0) === 36 && magics.has(name)) {
2321
- return this.magicContainer(name);
2325
+ return this.magicContainer(name, magics);
2326
+ }
2327
+ if (hooks.has(name)) {
2328
+ return this.magicContainer(name, hooks);
2322
2329
  }
2323
2330
  return void 0;
2324
2331
  }
@@ -2347,11 +2354,11 @@ Expression: ${expression}` : message);
2347
2354
  reactiveChild(vars, el = null) {
2348
2355
  return new _Scope(reactive(vars), this, el != null ? el : this.el);
2349
2356
  }
2350
- magicContainer(name) {
2357
+ magicContainer(name, registry) {
2351
2358
  if (!this.magicCache) this.magicCache = /* @__PURE__ */ new Map();
2352
2359
  const cached = this.magicCache.get(name);
2353
2360
  if (cached) return cached;
2354
- const getter = magics.get(name);
2361
+ const getter = registry.get(name);
2355
2362
  const scope = this;
2356
2363
  const container2 = {};
2357
2364
  Object.defineProperty(container2, name, {
@@ -2698,7 +2705,16 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2698
2705
  },
2699
2706
  effect(fn) {
2700
2707
  const owner = ownerScope();
2701
- owner.run(() => effect(fn, { scope: owner }));
2708
+ const hosted = () => {
2709
+ const previous = hookHost;
2710
+ hookHost = el;
2711
+ try {
2712
+ fn();
2713
+ } finally {
2714
+ hookHost = previous;
2715
+ }
2716
+ };
2717
+ owner.run(() => effect(hosted, { scope: owner }));
2702
2718
  },
2703
2719
  cleanup(fn) {
2704
2720
  addCleanup(el, fn);
@@ -2746,6 +2762,56 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2746
2762
  return;
2747
2763
  }
2748
2764
  initialized.add(el);
2765
+ const previousHost = hookHost;
2766
+ hookHost = el;
2767
+ try {
2768
+ walkElementDirectives(el, attrs, tagComponent, current2);
2769
+ } finally {
2770
+ hookHost = previousHost;
2771
+ }
2772
+ }
2773
+ var hookHost = null;
2774
+ function currentHookHost() {
2775
+ return hookHost;
2776
+ }
2777
+ function createDataScope(expression, parent, el) {
2778
+ let ast = null;
2779
+ try {
2780
+ ast = parse(expression);
2781
+ } catch (e) {
2782
+ ast = null;
2783
+ }
2784
+ const plain = ast && ast.t === "obj" && ast.props.every(
2785
+ (p2) => !p2.spread && !p2.keyExpr
2786
+ );
2787
+ if (!plain) {
2788
+ const raw = evaluateIn(expression, parent, "v-data");
2789
+ return parent.reactiveChild(raw && typeof raw === "object" ? raw : {}, el);
2790
+ }
2791
+ const scope = parent.reactiveChild({}, el);
2792
+ const props = ast.props;
2793
+ for (const prop of props) {
2794
+ if (prop.key === null) continue;
2795
+ try {
2796
+ if (prop.getter) {
2797
+ const compute = evaluate(prop.value, scope);
2798
+ Object.defineProperty(scope.data, prop.key, {
2799
+ enumerable: true,
2800
+ configurable: true,
2801
+ get: () => compute.call(scope.data)
2802
+ });
2803
+ } else {
2804
+ scope.data[prop.key] = evaluate(prop.value, scope);
2805
+ }
2806
+ } catch (err) {
2807
+ if (inDevelopment()) warnInvalidExpression(el, expression, expression, err);
2808
+ else handleError(err, "v-data");
2809
+ }
2810
+ }
2811
+ return scope;
2812
+ }
2813
+ function walkElementDirectives(el, attrs, tagComponent, scope) {
2814
+ let current2 = scope;
2749
2815
  for (const attr2 of attrs) {
2750
2816
  const def = directives.get(attr2.name);
2751
2817
  if (def == null ? void 0 : def.terminal) {
@@ -2765,11 +2831,10 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2765
2831
  nodeScopes.set(el, current2);
2766
2832
  }
2767
2833
  } else if (dataAttr || componentAttr) {
2768
- const raw = dataAttr ? evaluateIn(dataAttr.expression || "{}", current2, "v-data") : {};
2769
- current2 = current2.reactiveChild(raw && typeof raw === "object" ? raw : {}, el);
2834
+ current2 = createDataScope(dataAttr ? dataAttr.expression || "{}" : "{}", current2, el);
2770
2835
  nodeScopes.set(el, current2);
2771
2836
  }
2772
- const attributeScope = mountedComponent ? activeScope2 : current2;
2837
+ const attributeScope = mountedComponent ? scope : current2;
2773
2838
  for (const attr2 of attrs) {
2774
2839
  if (attr2.name === "data" || attr2.name === "component") continue;
2775
2840
  runDirective(el, attr2, attributeScope);
@@ -2926,9 +2991,9 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2926
2991
  var observer = null;
2927
2992
  var startHooks = [];
2928
2993
  function runPhase(target, after) {
2929
- for (const hook of startHooks) {
2994
+ for (const hook2 of startHooks) {
2930
2995
  try {
2931
- hook(target, after);
2996
+ hook2(target, after);
2932
2997
  } catch (error) {
2933
2998
  console.error("[Voodoo] a start hook failed", error);
2934
2999
  }
@@ -3312,10 +3377,10 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
3312
3377
  "destroyed"
3313
3378
  ]);
3314
3379
  function callHook(def, instance, name) {
3315
- const hook = def[name];
3316
- if (typeof hook !== "function") return;
3380
+ const hook2 = def[name];
3381
+ if (typeof hook2 !== "function") return;
3317
3382
  try {
3318
- hook.call(instance);
3383
+ hook2.call(instance);
3319
3384
  } catch (err) {
3320
3385
  handleError(err, `hook ${name}`);
3321
3386
  }
@@ -4774,6 +4839,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
4774
4839
  );
4775
4840
 
4776
4841
  // src/storage/index.ts
4842
+ init_reactivity();
4777
4843
  function createStorage(getStore, prefix = "") {
4778
4844
  const full = (key) => prefix + key;
4779
4845
  return {
@@ -4949,22 +5015,29 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
4949
5015
  };
4950
5016
  var THEME_KEY = "voodoo:theme";
4951
5017
  var picked = null;
5018
+ var revision = ref(0);
4952
5019
  var theme = {
4953
5020
  /** Theme chosen by the user, or `system` when never set. */
4954
5021
  get current() {
4955
5022
  var _a2, _b;
5023
+ void revision.value;
4956
5024
  return (_b = (_a2 = storage.get(THEME_KEY)) != null ? _a2 : picked) != null ? _b : "system";
4957
5025
  },
4958
5026
  /** Theme effectively applied, resolving `system`. */
4959
5027
  get resolved() {
4960
5028
  const value = this.current;
4961
5029
  if (value !== "system") return value;
5030
+ if (typeof document !== "undefined") {
5031
+ const authored = document.documentElement.getAttribute("data-theme");
5032
+ if (authored === "light" || authored === "dark") return authored;
5033
+ }
4962
5034
  if (typeof matchMedia === "undefined") return "light";
4963
5035
  return matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
4964
5036
  },
4965
5037
  set(value) {
4966
5038
  picked = value;
4967
5039
  storage.set(THEME_KEY, value);
5040
+ revision.value++;
4968
5041
  this.apply();
4969
5042
  },
4970
5043
  toggle() {
@@ -4998,8 +5071,17 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
4998
5071
  init() {
4999
5072
  if (typeof document === "undefined") return;
5000
5073
  this.apply();
5074
+ if (typeof MutationObserver !== "undefined") {
5075
+ new MutationObserver(() => {
5076
+ revision.value++;
5077
+ }).observe(document.documentElement, {
5078
+ attributes: true,
5079
+ attributeFilter: ["data-theme"]
5080
+ });
5081
+ }
5001
5082
  if (typeof matchMedia === "undefined") return;
5002
5083
  matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
5084
+ revision.value++;
5003
5085
  if (this.current === "system") this.apply();
5004
5086
  });
5005
5087
  }
@@ -5143,6 +5225,141 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5143
5225
  );
5144
5226
  }
5145
5227
 
5228
+ // src/hooks/index.ts
5229
+ init_reactivity();
5230
+ var tables = /* @__PURE__ */ new WeakMap();
5231
+ function tableFor(scope) {
5232
+ var _a2, _b, _c;
5233
+ const host = (_b = (_a2 = currentHookHost()) != null ? _a2 : scope.el) != null ? _b : scope;
5234
+ let table = tables.get(host);
5235
+ if (!table) {
5236
+ table = { slots: [], index: 0, scheduled: false, bound: false };
5237
+ tables.set(host, table);
5238
+ }
5239
+ const el = (_c = currentHookHost()) != null ? _c : scope.el;
5240
+ if (!table.bound && el) {
5241
+ table.bound = true;
5242
+ const owned = table;
5243
+ addCleanup(el, () => {
5244
+ for (const slot of owned.slots) {
5245
+ if (slot.dispose) slot.dispose();
5246
+ if (slot.runner) stop(slot.runner);
5247
+ }
5248
+ owned.slots.length = 0;
5249
+ });
5250
+ }
5251
+ if (!table.scheduled) {
5252
+ table.scheduled = true;
5253
+ const pending = table;
5254
+ queueMicrotask(() => {
5255
+ pending.index = 0;
5256
+ pending.scheduled = false;
5257
+ });
5258
+ }
5259
+ return table;
5260
+ }
5261
+ function nextSlot(scope, kind) {
5262
+ const table = tableFor(scope);
5263
+ const at = table.index++;
5264
+ let slot = table.slots[at];
5265
+ if (!slot || slot.kind !== kind) {
5266
+ if (slot) {
5267
+ if (slot.dispose) slot.dispose();
5268
+ if (slot.runner) stop(slot.runner);
5269
+ }
5270
+ slot = { kind, deps: null, value: void 0 };
5271
+ table.slots[at] = slot;
5272
+ }
5273
+ return slot;
5274
+ }
5275
+ function depsChanged(previous, next) {
5276
+ if (!previous || !next) return true;
5277
+ if (previous.length !== next.length) return true;
5278
+ for (let i = 0; i < next.length; i++) {
5279
+ if (!Object.is(previous[i], next[i])) return true;
5280
+ }
5281
+ return false;
5282
+ }
5283
+ function normalizeDeps(deps) {
5284
+ return Array.isArray(deps) ? deps.slice() : null;
5285
+ }
5286
+ function useState(scope, initial) {
5287
+ const slot = nextSlot(scope, "state");
5288
+ if (slot.value === void 0) slot.value = ref(initial);
5289
+ return slot.value;
5290
+ }
5291
+ function useEffect(scope, fn, deps) {
5292
+ const slot = nextSlot(scope, "effect");
5293
+ const next = normalizeDeps(deps);
5294
+ const runCleanup = () => {
5295
+ if (slot.dispose) {
5296
+ const dispose = slot.dispose;
5297
+ slot.dispose = void 0;
5298
+ dispose();
5299
+ }
5300
+ };
5301
+ if (next) {
5302
+ const first = slot.deps === null && !slot.runner;
5303
+ if (first || depsChanged(slot.deps, next)) {
5304
+ slot.deps = next;
5305
+ runCleanup();
5306
+ const result = fn();
5307
+ if (typeof result === "function") slot.dispose = result;
5308
+ }
5309
+ return;
5310
+ }
5311
+ if (slot.runner) return;
5312
+ slot.deps = null;
5313
+ slot.runner = effect(() => {
5314
+ runCleanup();
5315
+ const result = fn();
5316
+ if (typeof result === "function") slot.dispose = result;
5317
+ });
5318
+ }
5319
+ function useMemo(scope, fn, deps) {
5320
+ const slot = nextSlot(scope, "memo");
5321
+ const next = normalizeDeps(deps);
5322
+ if (!next) {
5323
+ if (!slot.value) slot.value = computed(fn);
5324
+ return slot.value;
5325
+ }
5326
+ if (!slot.value) {
5327
+ slot.value = ref(fn());
5328
+ slot.deps = next;
5329
+ } else if (depsChanged(slot.deps, next)) {
5330
+ slot.deps = next;
5331
+ slot.value.value = fn();
5332
+ }
5333
+ return slot.value;
5334
+ }
5335
+ function useRef(scope, initial) {
5336
+ const slot = nextSlot(scope, "ref");
5337
+ if (!slot.value) slot.value = markRaw({ current: initial });
5338
+ return slot.value;
5339
+ }
5340
+ function useContext(name, initial) {
5341
+ if (initial !== void 0 && !(name in allStores)) {
5342
+ store(name, initial);
5343
+ }
5344
+ return allStores[name];
5345
+ }
5346
+ function installHooks() {
5347
+ hook("useState", (scope) => (initial) => useState(scope, initial));
5348
+ hook(
5349
+ "useEffect",
5350
+ (scope) => (fn, deps) => useEffect(scope, fn, deps)
5351
+ );
5352
+ hook(
5353
+ "useMemo",
5354
+ (scope) => (fn, deps) => useMemo(scope, fn, deps)
5355
+ );
5356
+ hook("useRef", (scope) => (initial) => useRef(scope, initial));
5357
+ hook(
5358
+ "useContext",
5359
+ () => (name, initial) => useContext(name, initial)
5360
+ );
5361
+ }
5362
+
5146
5363
  // src/http/resource.ts
5147
5364
  init_reactivity();
5148
5365
  function pick(value, path) {
@@ -6747,6 +6964,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
6747
6964
  setScopeMarker(markNodeScope);
6748
6965
  setDirectiveRegistrar(directive);
6749
6966
  installMagics();
6967
+ installHooks();
6750
6968
  var eventBus = /* @__PURE__ */ new Map();
6751
6969
  function on(name, handler) {
6752
6970
  let set2 = eventBus.get(name);
@@ -6782,7 +7000,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
6782
7000
  }
6783
7001
  function directive(name, definition) {
6784
7002
  var _a2, _b;
6785
- const hooks = typeof definition === "function" ? { mounted: definition, updated: definition } : definition;
7003
+ const hooks2 = typeof definition === "function" ? { mounted: definition, updated: definition } : definition;
6786
7004
  defineDirective(
6787
7005
  name,
6788
7006
  (ctx) => {
@@ -6802,38 +7020,38 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
6802
7020
  instance: (_b3 = (_a4 = ctx.scope.owner) == null ? void 0 : _a4.component) != null ? _b3 : null
6803
7021
  };
6804
7022
  };
6805
- const initial = hooks.raw ? ctx.expression : ctx.evaluate();
6806
- (_a3 = hooks.created) == null ? void 0 : _a3.call(hooks, ctx.el, makeBinding(initial));
6807
- (_b2 = hooks.beforeMount) == null ? void 0 : _b2.call(hooks, ctx.el, makeBinding(initial));
7023
+ const initial = hooks2.raw ? ctx.expression : ctx.evaluate();
7024
+ (_a3 = hooks2.created) == null ? void 0 : _a3.call(hooks2, ctx.el, makeBinding(initial));
7025
+ (_b2 = hooks2.beforeMount) == null ? void 0 : _b2.call(hooks2, ctx.el, makeBinding(initial));
6808
7026
  ctx.effect(() => {
6809
7027
  var _a4, _b3;
6810
- const value = hooks.raw ? ctx.expression : ctx.evaluate();
7028
+ const value = hooks2.raw ? ctx.expression : ctx.evaluate();
6811
7029
  if (!mounted) {
6812
7030
  mounted = true;
6813
7031
  oldValue = value;
6814
- (_a4 = hooks.mounted) == null ? void 0 : _a4.call(hooks, ctx.el, makeBinding(value));
7032
+ (_a4 = hooks2.mounted) == null ? void 0 : _a4.call(hooks2, ctx.el, makeBinding(value));
6815
7033
  return;
6816
7034
  }
6817
7035
  if (value === oldValue) return;
6818
7036
  const binding = makeBinding(value);
6819
- (_b3 = hooks.updated) == null ? void 0 : _b3.call(hooks, ctx.el, binding);
7037
+ (_b3 = hooks2.updated) == null ? void 0 : _b3.call(hooks2, ctx.el, binding);
6820
7038
  oldValue = value;
6821
7039
  });
6822
7040
  ctx.cleanup(() => {
6823
7041
  var _a4, _b3;
6824
7042
  const binding = makeBinding(oldValue);
6825
- (_a4 = hooks.beforeUnmount) == null ? void 0 : _a4.call(hooks, ctx.el, binding);
6826
- (_b3 = hooks.unmounted) == null ? void 0 : _b3.call(hooks, ctx.el, binding);
7043
+ (_a4 = hooks2.beforeUnmount) == null ? void 0 : _a4.call(hooks2, ctx.el, binding);
7044
+ (_b3 = hooks2.unmounted) == null ? void 0 : _b3.call(hooks2, ctx.el, binding);
6827
7045
  });
6828
7046
  },
6829
- { priority: (_a2 = hooks.priority) != null ? _a2 : PRIORITY.DEFAULT, terminal: (_b = hooks.terminal) != null ? _b : false }
7047
+ { priority: (_a2 = hooks2.priority) != null ? _a2 : PRIORITY.DEFAULT, terminal: (_b = hooks2.terminal) != null ? _b : false }
6830
7048
  );
6831
7049
  }
6832
7050
  function data(values) {
6833
7051
  Object.defineProperties(rootScope.data, Object.getOwnPropertyDescriptors(values));
6834
7052
  return rootScope.data;
6835
7053
  }
6836
- var version2 = "0.11.2";
7054
+ var version2 = "0.12.1";
6837
7055
  var core = {
6838
7056
  // Utilities first: Voodoo's own names can override.
6839
7057
  ...utils_exports,