@json-render/vue 0.17.0 → 0.19.0

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.
package/dist/index.mjs CHANGED
@@ -174,7 +174,10 @@ import {
174
174
  } from "vue";
175
175
  import {
176
176
  resolveAction,
177
- executeAction
177
+ executeAction,
178
+ nextActionDispatchId,
179
+ notifyActionDispatch,
180
+ notifyActionSettle
178
181
  } from "@json-render/core";
179
182
 
180
183
  // src/composables/validation.ts
@@ -411,109 +414,141 @@ var ActionProvider = defineComponent4({
411
414
  };
412
415
  const execute = async (binding) => {
413
416
  const resolved = resolveAction(binding, getSnapshot());
414
- if (resolved.action === "setState" && resolved.params) {
415
- const statePath = resolved.params.statePath;
416
- const value = resolved.params.value;
417
- if (statePath) {
418
- set(statePath, value);
417
+ const dispatchId = nextActionDispatchId();
418
+ const dispatchedAt = Date.now();
419
+ notifyActionDispatch({
420
+ id: dispatchId,
421
+ name: resolved.action,
422
+ params: resolved.params,
423
+ at: dispatchedAt
424
+ });
425
+ let __ok = true;
426
+ let __error = void 0;
427
+ try {
428
+ if (resolved.action === "setState" && resolved.params) {
429
+ const statePath = resolved.params.statePath;
430
+ const value = resolved.params.value;
431
+ if (statePath) {
432
+ set(statePath, value);
433
+ }
434
+ return;
419
435
  }
420
- return;
421
- }
422
- if (resolved.action === "pushState" && resolved.params) {
423
- const statePath = resolved.params.statePath;
424
- const rawValue = resolved.params.value;
425
- if (statePath) {
426
- const resolvedValue = deepResolveValue(rawValue, get);
427
- const arr = get(statePath) ?? [];
428
- set(statePath, [...arr, resolvedValue]);
429
- const clearStatePath = resolved.params.clearStatePath;
430
- if (clearStatePath) {
431
- set(clearStatePath, "");
436
+ if (resolved.action === "pushState" && resolved.params) {
437
+ const statePath = resolved.params.statePath;
438
+ const rawValue = resolved.params.value;
439
+ if (statePath) {
440
+ const resolvedValue = deepResolveValue(rawValue, get);
441
+ const arr = get(statePath) ?? [];
442
+ set(statePath, [...arr, resolvedValue]);
443
+ const clearStatePath = resolved.params.clearStatePath;
444
+ if (clearStatePath) {
445
+ set(clearStatePath, "");
446
+ }
432
447
  }
448
+ return;
433
449
  }
434
- return;
435
- }
436
- if (resolved.action === "removeState" && resolved.params) {
437
- const statePath = resolved.params.statePath;
438
- const index = resolved.params.index;
439
- if (statePath !== void 0 && index !== void 0) {
440
- const arr = get(statePath) ?? [];
441
- set(
442
- statePath,
443
- arr.filter((_, i) => i !== index)
444
- );
450
+ if (resolved.action === "removeState" && resolved.params) {
451
+ const statePath = resolved.params.statePath;
452
+ const index = resolved.params.index;
453
+ if (statePath !== void 0 && index !== void 0) {
454
+ const arr = get(statePath) ?? [];
455
+ set(
456
+ statePath,
457
+ arr.filter((_, i) => i !== index)
458
+ );
459
+ }
460
+ return;
445
461
  }
446
- return;
447
- }
448
- if (resolved.action === "validateForm") {
449
- const validateAll = validation?.validateAll;
450
- if (!validateAll) {
451
- console.warn(
452
- "validateForm action was dispatched but no ValidationProvider is connected. Ensure ValidationProvider is rendered inside the provider tree."
453
- );
462
+ if (resolved.action === "validateForm") {
463
+ const validateAll = validation?.validateAll;
464
+ if (!validateAll) {
465
+ console.warn(
466
+ "validateForm action was dispatched but no ValidationProvider is connected. Ensure ValidationProvider is rendered inside the provider tree."
467
+ );
468
+ return;
469
+ }
470
+ const valid = validateAll();
471
+ const errors = {};
472
+ for (const [path, fs] of Object.entries(validation.fieldStates)) {
473
+ if (fs.result && !fs.result.valid) {
474
+ errors[path] = fs.result.errors;
475
+ }
476
+ }
477
+ const statePath = resolved.params?.statePath || "/formValidation";
478
+ set(statePath, { valid, errors });
454
479
  return;
455
480
  }
456
- const valid = validateAll();
457
- const errors = {};
458
- for (const [path, fs] of Object.entries(validation.fieldStates)) {
459
- if (fs.result && !fs.result.valid) {
460
- errors[path] = fs.result.errors;
481
+ if (resolved.action === "push" && resolved.params) {
482
+ const screen = resolved.params.screen;
483
+ if (screen) {
484
+ const currentScreen = get("/currentScreen");
485
+ const navStack = get("/navStack") ?? [];
486
+ if (currentScreen) {
487
+ set("/navStack", [...navStack, currentScreen]);
488
+ } else {
489
+ set("/navStack", [...navStack, ""]);
490
+ }
491
+ set("/currentScreen", screen);
461
492
  }
493
+ return;
462
494
  }
463
- const statePath = resolved.params?.statePath || "/formValidation";
464
- set(statePath, { valid, errors });
465
- return;
466
- }
467
- if (resolved.action === "push" && resolved.params) {
468
- const screen = resolved.params.screen;
469
- if (screen) {
470
- const currentScreen = get("/currentScreen");
495
+ if (resolved.action === "pop") {
471
496
  const navStack = get("/navStack") ?? [];
472
- if (currentScreen) {
473
- set("/navStack", [...navStack, currentScreen]);
474
- } else {
475
- set("/navStack", [...navStack, ""]);
497
+ if (navStack.length > 0) {
498
+ const previousScreen = navStack[navStack.length - 1];
499
+ set("/navStack", navStack.slice(0, -1));
500
+ if (previousScreen) {
501
+ set("/currentScreen", previousScreen);
502
+ } else {
503
+ set("/currentScreen", void 0);
504
+ }
476
505
  }
477
- set("/currentScreen", screen);
506
+ return;
478
507
  }
479
- return;
480
- }
481
- if (resolved.action === "pop") {
482
- const navStack = get("/navStack") ?? [];
483
- if (navStack.length > 0) {
484
- const previousScreen = navStack[navStack.length - 1];
485
- set("/navStack", navStack.slice(0, -1));
486
- if (previousScreen) {
487
- set("/currentScreen", previousScreen);
488
- } else {
489
- set("/currentScreen", void 0);
508
+ const handler = handlers.value[resolved.action];
509
+ if (!handler) {
510
+ console.warn(`No handler registered for action: ${resolved.action}`);
511
+ return;
512
+ }
513
+ if (resolved.confirm) {
514
+ await new Promise((resolve, reject) => {
515
+ pendingConfirmation.value = {
516
+ action: resolved,
517
+ handler,
518
+ resolve: () => {
519
+ pendingConfirmation.value = null;
520
+ resolve();
521
+ },
522
+ reject: () => {
523
+ pendingConfirmation.value = null;
524
+ reject(new Error("Action cancelled"));
525
+ }
526
+ };
527
+ });
528
+ const addLoading2 = new Set(loadingActions.value);
529
+ addLoading2.add(resolved.action);
530
+ loadingActions.value = addLoading2;
531
+ try {
532
+ await executeAction({
533
+ action: resolved,
534
+ handler,
535
+ setState: set,
536
+ navigate: props.navigate,
537
+ executeAction: async (name) => {
538
+ const subBinding = { action: name };
539
+ await execute(subBinding);
540
+ }
541
+ });
542
+ } finally {
543
+ const removeLoading = new Set(loadingActions.value);
544
+ removeLoading.delete(resolved.action);
545
+ loadingActions.value = removeLoading;
490
546
  }
547
+ return;
491
548
  }
492
- return;
493
- }
494
- const handler = handlers.value[resolved.action];
495
- if (!handler) {
496
- console.warn(`No handler registered for action: ${resolved.action}`);
497
- return;
498
- }
499
- if (resolved.confirm) {
500
- await new Promise((resolve, reject) => {
501
- pendingConfirmation.value = {
502
- action: resolved,
503
- handler,
504
- resolve: () => {
505
- pendingConfirmation.value = null;
506
- resolve();
507
- },
508
- reject: () => {
509
- pendingConfirmation.value = null;
510
- reject(new Error("Action cancelled"));
511
- }
512
- };
513
- });
514
- const addLoading2 = new Set(loadingActions.value);
515
- addLoading2.add(resolved.action);
516
- loadingActions.value = addLoading2;
549
+ const addLoading = new Set(loadingActions.value);
550
+ addLoading.add(resolved.action);
551
+ loadingActions.value = addLoading;
517
552
  try {
518
553
  await executeAction({
519
554
  action: resolved,
@@ -530,26 +565,20 @@ var ActionProvider = defineComponent4({
530
565
  removeLoading.delete(resolved.action);
531
566
  loadingActions.value = removeLoading;
532
567
  }
533
- return;
534
- }
535
- const addLoading = new Set(loadingActions.value);
536
- addLoading.add(resolved.action);
537
- loadingActions.value = addLoading;
538
- try {
539
- await executeAction({
540
- action: resolved,
541
- handler,
542
- setState: set,
543
- navigate: props.navigate,
544
- executeAction: async (name) => {
545
- const subBinding = { action: name };
546
- await execute(subBinding);
547
- }
548
- });
568
+ } catch (err) {
569
+ __ok = false;
570
+ __error = err;
571
+ throw err;
549
572
  } finally {
550
- const removeLoading = new Set(loadingActions.value);
551
- removeLoading.delete(resolved.action);
552
- loadingActions.value = removeLoading;
573
+ const now = Date.now();
574
+ notifyActionSettle({
575
+ id: dispatchId,
576
+ name: resolved.action,
577
+ ok: __ok,
578
+ at: now,
579
+ durationMs: now - dispatchedAt,
580
+ error: __error
581
+ });
553
582
  }
554
583
  };
555
584
  const confirm = () => pendingConfirmation.value?.resolve();
@@ -1231,6 +1260,7 @@ import {
1231
1260
  defineComponent as defineComponent6,
1232
1261
  h as h2,
1233
1262
  inject as inject6,
1263
+ onBeforeUnmount,
1234
1264
  onErrorCaptured,
1235
1265
  provide as provide6,
1236
1266
  ref as ref5,
@@ -1241,7 +1271,10 @@ import {
1241
1271
  resolveBindings,
1242
1272
  resolveActionParam,
1243
1273
  evaluateVisibility as evaluateVisibility2,
1244
- getByPath as getByPath3
1274
+ getByPath as getByPath3,
1275
+ createDirectiveRegistry,
1276
+ isDevtoolsActive,
1277
+ subscribeDevtoolsActive
1245
1278
  } from "@json-render/core";
1246
1279
  var EMPTY_FUNCTIONS = {};
1247
1280
  var FUNCTIONS_KEY = /* @__PURE__ */ Symbol("json-render:functions");
@@ -1265,6 +1298,29 @@ function useFunctions() {
1265
1298
  computed6(() => EMPTY_FUNCTIONS)
1266
1299
  );
1267
1300
  }
1301
+ var DIRECTIVES_KEY = /* @__PURE__ */ Symbol("json-render:directives");
1302
+ var DirectivesProvider = defineComponent6({
1303
+ name: "DirectivesProvider",
1304
+ props: {
1305
+ directives: {
1306
+ type: Array,
1307
+ default: void 0
1308
+ }
1309
+ },
1310
+ setup(props, { slots }) {
1311
+ const registry = computed6(
1312
+ () => props.directives ? createDirectiveRegistry(props.directives) : void 0
1313
+ );
1314
+ provide6(DIRECTIVES_KEY, registry);
1315
+ return () => slots.default?.();
1316
+ }
1317
+ });
1318
+ function useDirectives() {
1319
+ return inject6(
1320
+ DIRECTIVES_KEY,
1321
+ computed6(() => void 0)
1322
+ );
1323
+ }
1268
1324
  var ElementErrorBoundary = defineComponent6({
1269
1325
  name: "ElementErrorBoundary",
1270
1326
  props: {
@@ -1309,6 +1365,14 @@ async function resolveAndExecuteBindings(actionBindings, ctx, getSnapshot, execu
1309
1365
  if (cancelled?.()) break;
1310
1366
  }
1311
1367
  }
1368
+ function useDevtoolsActive() {
1369
+ const active = ref5(isDevtoolsActive());
1370
+ const unsub = subscribeDevtoolsActive(() => {
1371
+ active.value = isDevtoolsActive();
1372
+ });
1373
+ onBeforeUnmount(unsub);
1374
+ return active;
1375
+ }
1312
1376
  var ElementRenderer = defineComponent6({
1313
1377
  name: "JsonRenderElement",
1314
1378
  props: {
@@ -1316,6 +1380,10 @@ var ElementRenderer = defineComponent6({
1316
1380
  type: Object,
1317
1381
  required: true
1318
1382
  },
1383
+ elementKey: {
1384
+ type: String,
1385
+ default: void 0
1386
+ },
1319
1387
  spec: {
1320
1388
  type: Object,
1321
1389
  required: true
@@ -1334,11 +1402,13 @@ var ElementRenderer = defineComponent6({
1334
1402
  }
1335
1403
  },
1336
1404
  setup(props) {
1405
+ const devtoolsActive = useDevtoolsActive();
1337
1406
  const repeatScope = useRepeatScope();
1338
1407
  const { ctx: visibilityCtx } = useVisibility();
1339
1408
  const { execute } = useActions();
1340
1409
  const { getSnapshot, state: watchState } = useStateStore();
1341
1410
  const functions = useFunctions();
1411
+ const directives = useDirectives();
1342
1412
  const fullCtx = computed6(() => {
1343
1413
  const base = repeatScope ? {
1344
1414
  ...visibilityCtx.value,
@@ -1347,6 +1417,7 @@ var ElementRenderer = defineComponent6({
1347
1417
  repeatBasePath: repeatScope.basePath
1348
1418
  } : { ...visibilityCtx.value };
1349
1419
  base.functions = functions.value;
1420
+ base.directives = directives.value;
1350
1421
  return base;
1351
1422
  });
1352
1423
  const emitEvent = async (eventName) => {
@@ -1448,28 +1519,33 @@ var ElementRenderer = defineComponent6({
1448
1519
  return h2(ElementRenderer, {
1449
1520
  key: childKey,
1450
1521
  element: childElement,
1522
+ elementKey: childKey,
1451
1523
  spec: props.spec,
1452
1524
  registry: props.registry,
1453
1525
  loading: props.loading,
1454
1526
  fallback: props.fallback
1455
1527
  });
1456
1528
  }).filter((n) => n !== null) ?? void 0;
1529
+ const componentVNode = h2(
1530
+ Component,
1531
+ {
1532
+ element: resolvedElement,
1533
+ emit: emitEvent,
1534
+ on: onEvent,
1535
+ bindings: elementBindings,
1536
+ loading: props.loading
1537
+ },
1538
+ { default: () => childrenVNodes }
1539
+ );
1540
+ const tagged = devtoolsActive.value && props.elementKey ? h2(
1541
+ "span",
1542
+ { "data-jr-key": props.elementKey, style: "display:contents" },
1543
+ [componentVNode]
1544
+ ) : componentVNode;
1457
1545
  return h2(
1458
1546
  ElementErrorBoundary,
1459
1547
  { elementType: resolvedElement.type },
1460
- {
1461
- default: () => h2(
1462
- Component,
1463
- {
1464
- element: resolvedElement,
1465
- emit: emitEvent,
1466
- on: onEvent,
1467
- bindings: elementBindings,
1468
- loading: props.loading
1469
- },
1470
- { default: () => childrenVNodes }
1471
- )
1472
- }
1548
+ { default: () => tagged }
1473
1549
  );
1474
1550
  };
1475
1551
  }
@@ -1527,6 +1603,7 @@ var RepeatChildren = defineComponent6({
1527
1603
  return h2(ElementRenderer, {
1528
1604
  key: childKey,
1529
1605
  element: childElement,
1606
+ elementKey: childKey,
1530
1607
  spec: props.spec,
1531
1608
  registry: props.registry,
1532
1609
  loading: props.loading,
@@ -1566,6 +1643,7 @@ var Renderer = defineComponent6({
1566
1643
  if (!rootElement) return null;
1567
1644
  return h2(ElementRenderer, {
1568
1645
  element: rootElement,
1646
+ elementKey: props.spec.root,
1569
1647
  spec: props.spec,
1570
1648
  registry: props.registry,
1571
1649
  loading: props.loading,
@@ -1619,6 +1697,10 @@ var JSONUIProvider = defineComponent6({
1619
1697
  type: Object,
1620
1698
  default: void 0
1621
1699
  },
1700
+ directives: {
1701
+ type: Array,
1702
+ default: void 0
1703
+ },
1622
1704
  onStateChange: {
1623
1705
  type: Function,
1624
1706
  default: void 0
@@ -1646,10 +1728,16 @@ var JSONUIProvider = defineComponent6({
1646
1728
  FunctionsProvider,
1647
1729
  { functions: props.functions },
1648
1730
  {
1649
- default: () => [
1650
- slots.default?.(),
1651
- h2(ConfirmationDialogManager)
1652
- ]
1731
+ default: () => h2(
1732
+ DirectivesProvider,
1733
+ { directives: props.directives },
1734
+ {
1735
+ default: () => [
1736
+ slots.default?.(),
1737
+ h2(ConfirmationDialogManager)
1738
+ ]
1739
+ }
1740
+ )
1653
1741
  }
1654
1742
  )
1655
1743
  }
@@ -1755,6 +1843,10 @@ function createRenderer(catalog, components) {
1755
1843
  type: Object,
1756
1844
  default: void 0
1757
1845
  },
1846
+ directives: {
1847
+ type: Array,
1848
+ default: void 0
1849
+ },
1758
1850
  loading: {
1759
1851
  type: Boolean,
1760
1852
  default: void 0
@@ -1793,15 +1885,21 @@ function createRenderer(catalog, components) {
1793
1885
  FunctionsProvider,
1794
1886
  { functions: rendererProps.functions },
1795
1887
  {
1796
- default: () => [
1797
- h2(Renderer, {
1798
- spec: rendererProps.spec,
1799
- registry,
1800
- loading: rendererProps.loading,
1801
- fallback: rendererProps.fallback
1802
- }),
1803
- h2(ConfirmationDialogManager)
1804
- ]
1888
+ default: () => h2(
1889
+ DirectivesProvider,
1890
+ { directives: rendererProps.directives },
1891
+ {
1892
+ default: () => [
1893
+ h2(Renderer, {
1894
+ spec: rendererProps.spec,
1895
+ registry,
1896
+ loading: rendererProps.loading,
1897
+ fallback: rendererProps.fallback
1898
+ }),
1899
+ h2(ConfirmationDialogManager)
1900
+ ]
1901
+ }
1902
+ )
1805
1903
  }
1806
1904
  )
1807
1905
  }