voodoojs 0.11.2 → 0.12.2

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-IGZSDZKU.js → chunk-7AKBELZA.js} +4 -4
  3. package/dist/{chunk-V3O3WOZH.js → chunk-AVXQPDQH.js} +4 -4
  4. package/dist/{chunk-AH2VXDZD.js → chunk-K2U3O36M.js} +193 -20
  5. package/dist/{chunk-IS3DR2KY.js → chunk-MEE2ZAKJ.js} +3 -3
  6. package/dist/{chunk-DJJB35SR.js → chunk-NVANUFWZ.js} +6 -6
  7. package/dist/{chunk-H2ZUEQWV.js → chunk-OWCQV42D.js} +112 -20
  8. package/dist/{chunk-KQYSJHZR.js → chunk-RTZEIVNA.js} +5 -5
  9. package/dist/{chunk-NFDXVIII.js → chunk-RXOLGHSU.js} +3 -3
  10. package/dist/{chunk-WJP3YGUI.js → chunk-S4BXAGAW.js} +4 -4
  11. package/dist/{chunk-DCE5WIGA.js → chunk-UGLD36KV.js} +5 -5
  12. package/dist/{chunk-UV5PMS7P.js → chunk-YV4I45SK.js} +4 -4
  13. package/dist/essential.cjs +297 -28
  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 +325 -34
  22. package/dist/index.d.cts +88 -4
  23. package/dist/index.d.ts +88 -4
  24. package/dist/index.js +38 -24
  25. package/dist/{query-DiQAS73Q.d.cts → query-D_BGQw8m.d.cts} +12 -1
  26. package/dist/{query-Cf-7iibE.d.ts → query-Dl6Urlwd.d.ts} +12 -1
  27. package/dist/reactivity.cjs +1 -1
  28. package/dist/reactivity.js +2 -2
  29. package/dist/socket.cjs +29 -2
  30. package/dist/socket.js +9 -9
  31. package/dist/style-GWGXWHB4.js +5 -0
  32. package/dist/utils.cjs +1 -1
  33. package/dist/utils.js +2 -2
  34. package/dist/voodoo.core.js +277 -27
  35. package/dist/voodoo.core.min.js +17 -17
  36. package/dist/voodoo.full.js +325 -36
  37. package/dist/voodoo.full.min.js +59 -55
  38. package/dist/voodoo.js +305 -30
  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.2
3
3
  * JavaScript feels like magic.
4
4
  * (c) 2026 Voodoo.js contributors. MIT License.
5
5
  */
@@ -1798,6 +1798,23 @@ ${pointer}`);
1798
1798
  "SharedWorker",
1799
1799
  "ServiceWorker"
1800
1800
  ]);
1801
+ function guardedTimer(name) {
1802
+ return function(handler, timeout, ...rest) {
1803
+ if (typeof handler !== "function") {
1804
+ throw new VoodooRuntimeError(
1805
+ `${name} needs a function. Passing a string would compile it, which this library never does.`
1806
+ );
1807
+ }
1808
+ const timer = globalThis[name];
1809
+ return timer(handler, timeout, ...rest);
1810
+ };
1811
+ }
1812
+ function forwardGlobal(name) {
1813
+ return function(...args) {
1814
+ const fn = globalThis[name];
1815
+ return fn(...args);
1816
+ };
1817
+ }
1801
1818
  var allowedGlobals = {
1802
1819
  Math,
1803
1820
  JSON,
@@ -1816,7 +1833,17 @@ ${pointer}`);
1816
1833
  isFinite,
1817
1834
  encodeURIComponent,
1818
1835
  decodeURIComponent,
1819
- console
1836
+ console,
1837
+ ...typeof setTimeout !== "undefined" ? {
1838
+ setTimeout: guardedTimer("setTimeout"),
1839
+ setInterval: guardedTimer("setInterval"),
1840
+ clearTimeout: forwardGlobal("clearTimeout"),
1841
+ clearInterval: forwardGlobal("clearInterval")
1842
+ } : {},
1843
+ ...typeof requestAnimationFrame !== "undefined" ? {
1844
+ requestAnimationFrame: forwardGlobal("requestAnimationFrame"),
1845
+ cancelAnimationFrame: forwardGlobal("cancelAnimationFrame")
1846
+ } : {}
1820
1847
  };
1821
1848
  var VoodooRuntimeError = class extends Error {
1822
1849
  constructor(message, expression) {
@@ -2263,6 +2290,10 @@ Expression: ${expression}` : message);
2263
2290
  function magic(name, getter) {
2264
2291
  magics.set(name.startsWith("$") ? name : `$${name}`, getter);
2265
2292
  }
2293
+ var hooks = /* @__PURE__ */ new Map();
2294
+ function hook(name, getter) {
2295
+ hooks.set(name, getter);
2296
+ }
2266
2297
  var Scope = class _Scope {
2267
2298
  // Assignment order matches the order the fields were declared in before, so
2268
2299
  // the properties are created in the same sequence they always were.
@@ -2318,7 +2349,10 @@ Expression: ${expression}` : message);
2318
2349
  s = s.parent;
2319
2350
  }
2320
2351
  if (name.charCodeAt(0) === 36 && magics.has(name)) {
2321
- return this.magicContainer(name);
2352
+ return this.magicContainer(name, magics);
2353
+ }
2354
+ if (hooks.has(name)) {
2355
+ return this.magicContainer(name, hooks);
2322
2356
  }
2323
2357
  return void 0;
2324
2358
  }
@@ -2347,11 +2381,11 @@ Expression: ${expression}` : message);
2347
2381
  reactiveChild(vars, el = null) {
2348
2382
  return new _Scope(reactive(vars), this, el != null ? el : this.el);
2349
2383
  }
2350
- magicContainer(name) {
2384
+ magicContainer(name, registry) {
2351
2385
  if (!this.magicCache) this.magicCache = /* @__PURE__ */ new Map();
2352
2386
  const cached = this.magicCache.get(name);
2353
2387
  if (cached) return cached;
2354
- const getter = magics.get(name);
2388
+ const getter = registry.get(name);
2355
2389
  const scope = this;
2356
2390
  const container2 = {};
2357
2391
  Object.defineProperty(container2, name, {
@@ -2753,7 +2787,16 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2753
2787
  },
2754
2788
  effect(fn) {
2755
2789
  const owner = ownerScope();
2756
- owner.run(() => effect(fn, { scope: owner }));
2790
+ const hosted = () => {
2791
+ const previous = hookHost;
2792
+ hookHost = el;
2793
+ try {
2794
+ fn();
2795
+ } finally {
2796
+ hookHost = previous;
2797
+ }
2798
+ };
2799
+ owner.run(() => effect(hosted, { scope: owner }));
2757
2800
  },
2758
2801
  cleanup(fn) {
2759
2802
  addCleanup(el, fn);
@@ -2801,6 +2844,56 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2801
2844
  return;
2802
2845
  }
2803
2846
  initialized.add(el);
2847
+ const previousHost = hookHost;
2848
+ hookHost = el;
2849
+ try {
2850
+ walkElementDirectives(el, attrs, tagComponent, current2);
2851
+ } finally {
2852
+ hookHost = previousHost;
2853
+ }
2854
+ }
2855
+ var hookHost = null;
2856
+ function currentHookHost() {
2857
+ return hookHost;
2858
+ }
2859
+ function createDataScope(expression, parent, el) {
2860
+ let ast = null;
2861
+ try {
2862
+ ast = parse(expression);
2863
+ } catch (e) {
2864
+ ast = null;
2865
+ }
2866
+ const plain = ast && ast.t === "obj" && ast.props.every(
2867
+ (p2) => !p2.spread && !p2.keyExpr
2868
+ );
2869
+ if (!plain) {
2870
+ const raw = evaluateIn(expression, parent, "v-data");
2871
+ return parent.reactiveChild(raw && typeof raw === "object" ? raw : {}, el);
2872
+ }
2873
+ const scope = parent.reactiveChild({}, el);
2874
+ const props = ast.props;
2875
+ for (const prop of props) {
2876
+ if (prop.key === null) continue;
2877
+ try {
2878
+ if (prop.getter) {
2879
+ const compute = evaluate(prop.value, scope);
2880
+ Object.defineProperty(scope.data, prop.key, {
2881
+ enumerable: true,
2882
+ configurable: true,
2883
+ get: () => compute.call(scope.data)
2884
+ });
2885
+ } else {
2886
+ scope.data[prop.key] = evaluate(prop.value, scope);
2887
+ }
2888
+ } catch (err) {
2889
+ if (inDevelopment()) warnInvalidExpression(el, expression, expression, err);
2890
+ else handleError(err, "v-data");
2891
+ }
2892
+ }
2893
+ return scope;
2894
+ }
2895
+ function walkElementDirectives(el, attrs, tagComponent, scope) {
2896
+ let current2 = scope;
2804
2897
  for (const attr2 of attrs) {
2805
2898
  const def = directives.get(attr2.name);
2806
2899
  if (def == null ? void 0 : def.terminal) {
@@ -2820,11 +2913,10 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2820
2913
  nodeScopes.set(el, current2);
2821
2914
  }
2822
2915
  } else if (dataAttr || componentAttr) {
2823
- const raw = dataAttr ? evaluateIn(dataAttr.expression || "{}", current2, "v-data") : {};
2824
- current2 = current2.reactiveChild(raw && typeof raw === "object" ? raw : {}, el);
2916
+ current2 = createDataScope(dataAttr ? dataAttr.expression || "{}" : "{}", current2, el);
2825
2917
  nodeScopes.set(el, current2);
2826
2918
  }
2827
- const attributeScope = mountedComponent ? activeScope2 : current2;
2919
+ const attributeScope = mountedComponent ? scope : current2;
2828
2920
  for (const attr2 of attrs) {
2829
2921
  if (attr2.name === "data" || attr2.name === "component") continue;
2830
2922
  runDirective(el, attr2, attributeScope);
@@ -2980,13 +3072,13 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
2980
3072
  var started = false;
2981
3073
  var observer = null;
2982
3074
  var startHooks = [];
2983
- function onStart(hook) {
2984
- startHooks.push(hook);
3075
+ function onStart(hook2) {
3076
+ startHooks.push(hook2);
2985
3077
  }
2986
3078
  function runPhase(target, after) {
2987
- for (const hook of startHooks) {
3079
+ for (const hook2 of startHooks) {
2988
3080
  try {
2989
- hook(target, after);
3081
+ hook2(target, after);
2990
3082
  } catch (error) {
2991
3083
  console.error("[Voodoo] a start hook failed", error);
2992
3084
  }
@@ -3370,10 +3462,10 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
3370
3462
  "destroyed"
3371
3463
  ]);
3372
3464
  function callHook(def, instance, name) {
3373
- const hook = def[name];
3374
- if (typeof hook !== "function") return;
3465
+ const hook2 = def[name];
3466
+ if (typeof hook2 !== "function") return;
3375
3467
  try {
3376
- hook.call(instance);
3468
+ hook2.call(instance);
3377
3469
  } catch (err) {
3378
3470
  handleError(err, `hook ${name}`);
3379
3471
  }
@@ -4832,6 +4924,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
4832
4924
  );
4833
4925
 
4834
4926
  // src/storage/index.ts
4927
+ init_reactivity();
4835
4928
  function createStorage(getStore, prefix = "") {
4836
4929
  const full = (key) => prefix + key;
4837
4930
  return {
@@ -5007,22 +5100,29 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5007
5100
  };
5008
5101
  var THEME_KEY = "voodoo:theme";
5009
5102
  var picked = null;
5103
+ var revision = ref(0);
5010
5104
  var theme = {
5011
5105
  /** Theme chosen by the user, or `system` when never set. */
5012
5106
  get current() {
5013
5107
  var _a2, _b;
5108
+ void revision.value;
5014
5109
  return (_b = (_a2 = storage.get(THEME_KEY)) != null ? _a2 : picked) != null ? _b : "system";
5015
5110
  },
5016
5111
  /** Theme effectively applied, resolving `system`. */
5017
5112
  get resolved() {
5018
5113
  const value = this.current;
5019
5114
  if (value !== "system") return value;
5115
+ if (typeof document !== "undefined") {
5116
+ const authored = document.documentElement.getAttribute("data-theme");
5117
+ if (authored === "light" || authored === "dark") return authored;
5118
+ }
5020
5119
  if (typeof matchMedia === "undefined") return "light";
5021
5120
  return matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
5022
5121
  },
5023
5122
  set(value) {
5024
5123
  picked = value;
5025
5124
  storage.set(THEME_KEY, value);
5125
+ revision.value++;
5026
5126
  this.apply();
5027
5127
  },
5028
5128
  toggle() {
@@ -5056,8 +5156,17 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5056
5156
  init() {
5057
5157
  if (typeof document === "undefined") return;
5058
5158
  this.apply();
5159
+ if (typeof MutationObserver !== "undefined") {
5160
+ new MutationObserver(() => {
5161
+ revision.value++;
5162
+ }).observe(document.documentElement, {
5163
+ attributes: true,
5164
+ attributeFilter: ["data-theme"]
5165
+ });
5166
+ }
5059
5167
  if (typeof matchMedia === "undefined") return;
5060
5168
  matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
5169
+ revision.value++;
5061
5170
  if (this.current === "system") this.apply();
5062
5171
  });
5063
5172
  }
@@ -5201,6 +5310,141 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
5201
5310
  );
5202
5311
  }
5203
5312
 
5313
+ // src/hooks/index.ts
5314
+ init_reactivity();
5315
+ var tables = /* @__PURE__ */ new WeakMap();
5316
+ function tableFor(scope) {
5317
+ var _a2, _b, _c;
5318
+ const host = (_b = (_a2 = currentHookHost()) != null ? _a2 : scope.el) != null ? _b : scope;
5319
+ let table = tables.get(host);
5320
+ if (!table) {
5321
+ table = { slots: [], index: 0, scheduled: false, bound: false };
5322
+ tables.set(host, table);
5323
+ }
5324
+ const el = (_c = currentHookHost()) != null ? _c : scope.el;
5325
+ if (!table.bound && el) {
5326
+ table.bound = true;
5327
+ const owned = table;
5328
+ addCleanup(el, () => {
5329
+ for (const slot of owned.slots) {
5330
+ if (slot.dispose) slot.dispose();
5331
+ if (slot.runner) stop(slot.runner);
5332
+ }
5333
+ owned.slots.length = 0;
5334
+ });
5335
+ }
5336
+ if (!table.scheduled) {
5337
+ table.scheduled = true;
5338
+ const pending2 = table;
5339
+ queueMicrotask(() => {
5340
+ pending2.index = 0;
5341
+ pending2.scheduled = false;
5342
+ });
5343
+ }
5344
+ return table;
5345
+ }
5346
+ function nextSlot(scope, kind) {
5347
+ const table = tableFor(scope);
5348
+ const at = table.index++;
5349
+ let slot = table.slots[at];
5350
+ if (!slot || slot.kind !== kind) {
5351
+ if (slot) {
5352
+ if (slot.dispose) slot.dispose();
5353
+ if (slot.runner) stop(slot.runner);
5354
+ }
5355
+ slot = { kind, deps: null, value: void 0 };
5356
+ table.slots[at] = slot;
5357
+ }
5358
+ return slot;
5359
+ }
5360
+ function depsChanged(previous, next) {
5361
+ if (!previous || !next) return true;
5362
+ if (previous.length !== next.length) return true;
5363
+ for (let i = 0; i < next.length; i++) {
5364
+ if (!Object.is(previous[i], next[i])) return true;
5365
+ }
5366
+ return false;
5367
+ }
5368
+ function normalizeDeps(deps) {
5369
+ return Array.isArray(deps) ? deps.slice() : null;
5370
+ }
5371
+ function useState(scope, initial) {
5372
+ const slot = nextSlot(scope, "state");
5373
+ if (slot.value === void 0) slot.value = ref(initial);
5374
+ return slot.value;
5375
+ }
5376
+ function useEffect(scope, fn, deps) {
5377
+ const slot = nextSlot(scope, "effect");
5378
+ const next = normalizeDeps(deps);
5379
+ const runCleanup = () => {
5380
+ if (slot.dispose) {
5381
+ const dispose = slot.dispose;
5382
+ slot.dispose = void 0;
5383
+ dispose();
5384
+ }
5385
+ };
5386
+ if (next) {
5387
+ const first = slot.deps === null && !slot.runner;
5388
+ if (first || depsChanged(slot.deps, next)) {
5389
+ slot.deps = next;
5390
+ runCleanup();
5391
+ const result = fn();
5392
+ if (typeof result === "function") slot.dispose = result;
5393
+ }
5394
+ return;
5395
+ }
5396
+ if (slot.runner) return;
5397
+ slot.deps = null;
5398
+ slot.runner = effect(() => {
5399
+ runCleanup();
5400
+ const result = fn();
5401
+ if (typeof result === "function") slot.dispose = result;
5402
+ });
5403
+ }
5404
+ function useMemo(scope, fn, deps) {
5405
+ const slot = nextSlot(scope, "memo");
5406
+ const next = normalizeDeps(deps);
5407
+ if (!next) {
5408
+ if (!slot.value) slot.value = computed(fn);
5409
+ return slot.value;
5410
+ }
5411
+ if (!slot.value) {
5412
+ slot.value = ref(fn());
5413
+ slot.deps = next;
5414
+ } else if (depsChanged(slot.deps, next)) {
5415
+ slot.deps = next;
5416
+ slot.value.value = fn();
5417
+ }
5418
+ return slot.value;
5419
+ }
5420
+ function useRef(scope, initial) {
5421
+ const slot = nextSlot(scope, "ref");
5422
+ if (!slot.value) slot.value = markRaw({ current: initial });
5423
+ return slot.value;
5424
+ }
5425
+ function useContext(name, initial) {
5426
+ if (initial !== void 0 && !(name in allStores)) {
5427
+ store(name, initial);
5428
+ }
5429
+ return allStores[name];
5430
+ }
5431
+ function installHooks() {
5432
+ hook("useState", (scope) => (initial) => useState(scope, initial));
5433
+ hook(
5434
+ "useEffect",
5435
+ (scope) => (fn, deps) => useEffect(scope, fn, deps)
5436
+ );
5437
+ hook(
5438
+ "useMemo",
5439
+ (scope) => (fn, deps) => useMemo(scope, fn, deps)
5440
+ );
5441
+ hook("useRef", (scope) => (initial) => useRef(scope, initial));
5442
+ hook(
5443
+ "useContext",
5444
+ () => (name, initial) => useContext(name, initial)
5445
+ );
5446
+ }
5447
+
5204
5448
  // src/http/resource.ts
5205
5449
  init_reactivity();
5206
5450
  function pick(value, path) {
@@ -6805,6 +7049,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
6805
7049
  setScopeMarker(markNodeScope);
6806
7050
  setDirectiveRegistrar(directive);
6807
7051
  installMagics();
7052
+ installHooks();
6808
7053
  var eventBus = /* @__PURE__ */ new Map();
6809
7054
  function on(name, handler) {
6810
7055
  let set2 = eventBus.get(name);
@@ -6840,7 +7085,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
6840
7085
  }
6841
7086
  function directive(name, definition) {
6842
7087
  var _a2, _b;
6843
- const hooks = typeof definition === "function" ? { mounted: definition, updated: definition } : definition;
7088
+ const hooks2 = typeof definition === "function" ? { mounted: definition, updated: definition } : definition;
6844
7089
  defineDirective(
6845
7090
  name,
6846
7091
  (ctx) => {
@@ -6860,38 +7105,38 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
6860
7105
  instance: (_b3 = (_a4 = ctx.scope.owner) == null ? void 0 : _a4.component) != null ? _b3 : null
6861
7106
  };
6862
7107
  };
6863
- const initial = hooks.raw ? ctx.expression : ctx.evaluate();
6864
- (_a3 = hooks.created) == null ? void 0 : _a3.call(hooks, ctx.el, makeBinding(initial));
6865
- (_b2 = hooks.beforeMount) == null ? void 0 : _b2.call(hooks, ctx.el, makeBinding(initial));
7108
+ const initial = hooks2.raw ? ctx.expression : ctx.evaluate();
7109
+ (_a3 = hooks2.created) == null ? void 0 : _a3.call(hooks2, ctx.el, makeBinding(initial));
7110
+ (_b2 = hooks2.beforeMount) == null ? void 0 : _b2.call(hooks2, ctx.el, makeBinding(initial));
6866
7111
  ctx.effect(() => {
6867
7112
  var _a4, _b3;
6868
- const value = hooks.raw ? ctx.expression : ctx.evaluate();
7113
+ const value = hooks2.raw ? ctx.expression : ctx.evaluate();
6869
7114
  if (!mounted2) {
6870
7115
  mounted2 = true;
6871
7116
  oldValue = value;
6872
- (_a4 = hooks.mounted) == null ? void 0 : _a4.call(hooks, ctx.el, makeBinding(value));
7117
+ (_a4 = hooks2.mounted) == null ? void 0 : _a4.call(hooks2, ctx.el, makeBinding(value));
6873
7118
  return;
6874
7119
  }
6875
7120
  if (value === oldValue) return;
6876
7121
  const binding = makeBinding(value);
6877
- (_b3 = hooks.updated) == null ? void 0 : _b3.call(hooks, ctx.el, binding);
7122
+ (_b3 = hooks2.updated) == null ? void 0 : _b3.call(hooks2, ctx.el, binding);
6878
7123
  oldValue = value;
6879
7124
  });
6880
7125
  ctx.cleanup(() => {
6881
7126
  var _a4, _b3;
6882
7127
  const binding = makeBinding(oldValue);
6883
- (_a4 = hooks.beforeUnmount) == null ? void 0 : _a4.call(hooks, ctx.el, binding);
6884
- (_b3 = hooks.unmounted) == null ? void 0 : _b3.call(hooks, ctx.el, binding);
7128
+ (_a4 = hooks2.beforeUnmount) == null ? void 0 : _a4.call(hooks2, ctx.el, binding);
7129
+ (_b3 = hooks2.unmounted) == null ? void 0 : _b3.call(hooks2, ctx.el, binding);
6885
7130
  });
6886
7131
  },
6887
- { priority: (_a2 = hooks.priority) != null ? _a2 : PRIORITY.DEFAULT, terminal: (_b = hooks.terminal) != null ? _b : false }
7132
+ { priority: (_a2 = hooks2.priority) != null ? _a2 : PRIORITY.DEFAULT, terminal: (_b = hooks2.terminal) != null ? _b : false }
6888
7133
  );
6889
7134
  }
6890
7135
  function data(values) {
6891
7136
  Object.defineProperties(rootScope.data, Object.getOwnPropertyDescriptors(values));
6892
7137
  return rootScope.data;
6893
7138
  }
6894
- var version2 = "0.11.2";
7139
+ var version2 = "0.12.2";
6895
7140
  var core = {
6896
7141
  // Utilities first: Voodoo's own names can override.
6897
7142
  ...utils_exports,
@@ -10057,6 +10302,7 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
10057
10302
  ensureUi();
10058
10303
  collapseOf(el);
10059
10304
  });
10305
+ var selfToggling = /* @__PURE__ */ new WeakSet();
10060
10306
  defineDirective("collapse-toggle", ({ el, expression, cleanup }) => {
10061
10307
  ensureUi();
10062
10308
  const target = resolveTarget(el, expression);
@@ -10065,6 +10311,8 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
10065
10311
  controller.triggers.add(el);
10066
10312
  controller.sync();
10067
10313
  makeInteractive(el, cleanup);
10314
+ selfToggling.add(el);
10315
+ cleanup(() => selfToggling.delete(el));
10068
10316
  const onClick = (event) => {
10069
10317
  event.preventDefault();
10070
10318
  controller.toggle();
@@ -10479,10 +10727,11 @@ Suggestion: attribute expressions accept a single value. If the logic spans more
10479
10727
  if (index === -1) return;
10480
10728
  event.preventDefault();
10481
10729
  const controller = controllers2[index];
10482
- if (single && !controller.open) {
10730
+ const ownToggle = selfToggling.has(header);
10731
+ if (single && (ownToggle ? controller.open : !controller.open)) {
10483
10732
  for (const other of controllers2) if (other !== controller) other.hide();
10484
10733
  }
10485
- controller.toggle();
10734
+ if (!ownToggle) controller.toggle();
10486
10735
  };
10487
10736
  const onKeyDown = (event) => {
10488
10737
  var _a2;
@@ -13360,12 +13609,15 @@ form.v-loading [type="submit"],form.v-loading button[disabled]{opacity:.6}
13360
13609
 
13361
13610
  // src/sound/index.ts
13362
13611
  init_registry();
13612
+ init_reactivity();
13613
+ init_style();
13363
13614
  var audioContext = null;
13364
13615
  var masterVolume = 0.35;
13365
13616
  var isMuted = false;
13366
13617
  var hasLoadedPreference = false;
13367
13618
  var VOLUME_KEY = "voodoo:sound:volume";
13368
13619
  var MUTE_KEY = "voodoo:sound:muted";
13620
+ var muteRevision = ref(0);
13369
13621
  function loadPreference() {
13370
13622
  if (hasLoadedPreference) return;
13371
13623
  hasLoadedPreference = true;
@@ -13681,6 +13933,7 @@ form.v-loading [type="submit"],form.v-loading button[disabled]{opacity:.6}
13681
13933
  loadPreference();
13682
13934
  isMuted = value;
13683
13935
  storage.set(MUTE_KEY, isMuted);
13936
+ muteRevision.value++;
13684
13937
  },
13685
13938
  /** Unmutes sound. */
13686
13939
  unmute() {
@@ -13692,8 +13945,18 @@ form.v-loading [type="submit"],form.v-loading button[disabled]{opacity:.6}
13692
13945
  this.mute(!isMuted);
13693
13946
  return isMuted;
13694
13947
  },
13695
- /** `true` when muted. */
13948
+ /**
13949
+ * `true` when muted.
13950
+ *
13951
+ * Reads a revision ref first, so that an expression asking whether sound is
13952
+ * muted actually re-runs when it changes. The state lives in a module
13953
+ * variable and in localStorage, both invisible to the Proxy, so
13954
+ * `v-show="$sound.muted"` used to render once and then never move: a page had
13955
+ * no way to show whether it was muted, which made the mute button look like
13956
+ * it did nothing at all.
13957
+ */
13696
13958
  get muted() {
13959
+ void muteRevision.value;
13697
13960
  loadPreference();
13698
13961
  return isMuted;
13699
13962
  },
@@ -13744,11 +14007,18 @@ form.v-loading [type="submit"],form.v-loading button[disabled]{opacity:.6}
13744
14007
  cleanup(() => el.removeEventListener(event, play));
13745
14008
  void scope;
13746
14009
  });
14010
+ var MUTE_CSS = `
14011
+ .v-muted{opacity:.55}
14012
+ .v-muted::after{content:" \\1F507";font-size:.9em}
14013
+ .v-mute-on::after{content:" \\1F50A";font-size:.9em}
14014
+ `;
13747
14015
  defineDirective("mute", ({ el, cleanup }) => {
14016
+ injectStyle("mute", MUTE_CSS);
13748
14017
  const sync = () => {
13749
14018
  const isMuted2 = sound.muted;
13750
14019
  el.setAttribute("aria-pressed", String(isMuted2));
13751
14020
  el.classList.toggle("v-muted", isMuted2);
14021
+ el.classList.toggle("v-mute-on", !isMuted2);
13752
14022
  };
13753
14023
  const toggle = () => {
13754
14024
  sound.toggle();
@@ -18097,8 +18367,22 @@ ${block(':root:not([data-theme="light"])', dark.vars)}
18097
18367
  }
18098
18368
  },
18099
18369
  methods: {
18100
- cell(row, column) {
18101
- const value = get(row, column.key);
18370
+ /**
18371
+ * A row may be an object keyed by column, or a positional array.
18372
+ *
18373
+ * Only the object form was ever read. The documentation's own example on
18374
+ * the components page passes `[['Ada', 'Engineer']]` against columns
18375
+ * `['Name', 'Role']`, and looking `'Name'` up on an array finds nothing, so
18376
+ * every cell rendered empty while the header row and the row count both
18377
+ * looked perfectly right — which is a hard failure to even notice, let
18378
+ * alone diagnose.
18379
+ *
18380
+ * The index comes from the template rather than `cols.indexOf(column)`,
18381
+ * because `cols` is a computed and identity is not guaranteed to survive a
18382
+ * recomputation.
18383
+ */
18384
+ cell(row, column, index) {
18385
+ const value = Array.isArray(row) && typeof index === "number" ? row[index] : get(row, column.key);
18102
18386
  if (value === null || value === void 0) return "";
18103
18387
  return String(value);
18104
18388
  },
@@ -18146,8 +18430,8 @@ ${block(':root:not([data-theme="light"])', dark.vars)}
18146
18430
  </thead>
18147
18431
  <tbody>
18148
18432
  <tr v-for="(row, index) in sorted" :key="index">
18149
- <td v-for="column in cols" :key="column.key" :style="alignStyle(column)"
18150
- v-text="cell(row, column)"></td>
18433
+ <td v-for="(column, ci) in cols" :key="column.key" :style="alignStyle(column)"
18434
+ v-text="cell(row, column, ci)"></td>
18151
18435
  </tr>
18152
18436
  <tr v-if="!sorted.length">
18153
18437
  <td class="v-table-empty" :colspan="cols.length || 1" v-text="empty"></td>
@@ -21790,9 +22074,14 @@ textarea.v-dialog-input{min-height:96px;resize:vertical}
21790
22074
  allowedGlobals.V = V2;
21791
22075
  allowedGlobals.Voodoo = V2;
21792
22076
  if (config.baseURL && ((_a2 = V2.http) == null ? void 0 : _a2.setBaseURL)) V2.http.setBaseURL(config.baseURL);
21793
- if (options.manual || !config.autoStart) return;
22077
+ theme.init();
22078
+ if (options.manual || !config.autoStart) {
22079
+ whenReady(() => {
22080
+ applySavedPalette();
22081
+ });
22082
+ return;
22083
+ }
21794
22084
  const boot = () => {
21795
- theme.init();
21796
22085
  applySavedPalette();
21797
22086
  V2.start();
21798
22087
  if (typeof V2.enableXrayShortcut === "function") V2.enableXrayShortcut();