@platforma-sdk/ui-vue 1.54.12 → 1.55.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.
Files changed (95) hide show
  1. package/.turbo/turbo-build.log +28 -23
  2. package/.turbo/turbo-formatter$colon$check.log +2 -2
  3. package/.turbo/turbo-linter$colon$check.log +2 -2
  4. package/.turbo/turbo-types$colon$check.log +1 -1
  5. package/CHANGELOG.md +21 -0
  6. package/dist/AgGridVue/useAgGridOptions.js +10 -9
  7. package/dist/AgGridVue/useAgGridOptions.js.map +1 -1
  8. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts +32 -40
  9. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts.map +1 -1
  10. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
  11. package/dist/components/PlAdvancedFilter/index.d.ts +2 -2
  12. package/dist/components/PlAdvancedFilter/index.d.ts.map +1 -1
  13. package/dist/components/PlAdvancedFilter/index.js.map +1 -1
  14. package/dist/components/PlAdvancedFilter/types.d.ts +9 -8
  15. package/dist/components/PlAdvancedFilter/types.d.ts.map +1 -1
  16. package/dist/components/PlAdvancedFilter/utils.js +38 -27
  17. package/dist/components/PlAdvancedFilter/utils.js.map +1 -1
  18. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts.map +1 -1
  19. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +161 -244
  20. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
  21. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js +9 -8
  22. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js.map +1 -1
  23. package/dist/components/PlAgDataTable/compositions/useFilterableColumns.d.ts +134 -0
  24. package/dist/components/PlAgDataTable/compositions/useFilterableColumns.d.ts.map +1 -0
  25. package/dist/components/PlAgDataTable/compositions/useFilterableColumns.js +33 -0
  26. package/dist/components/PlAgDataTable/compositions/useFilterableColumns.js.map +1 -0
  27. package/dist/components/PlAgDataTable/compositions/useGrid.d.ts +15 -0
  28. package/dist/components/PlAgDataTable/compositions/useGrid.d.ts.map +1 -0
  29. package/dist/components/PlAgDataTable/compositions/useGrid.js +113 -0
  30. package/dist/components/PlAgDataTable/compositions/useGrid.js.map +1 -0
  31. package/dist/components/PlAgDataTable/sources/row-number.d.ts.map +1 -1
  32. package/dist/components/PlAgDataTable/sources/row-number.js.map +1 -1
  33. package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts +1 -2
  34. package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts.map +1 -1
  35. package/dist/components/PlAgDataTable/sources/table-source-v2.js +47 -62
  36. package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
  37. package/dist/components/PlAgDataTable/sources/table-state-v2.d.ts +4 -4
  38. package/dist/components/PlAgDataTable/sources/table-state-v2.d.ts.map +1 -1
  39. package/dist/components/PlAgDataTable/sources/table-state-v2.js +105 -95
  40. package/dist/components/PlAgDataTable/sources/table-state-v2.js.map +1 -1
  41. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js +11 -10
  42. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js.map +1 -1
  43. package/dist/components/PlAgRowNumHeader.vue.js +10 -9
  44. package/dist/components/PlAgRowNumHeader.vue.js.map +1 -1
  45. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue.d.ts +10 -0
  46. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue.d.ts.map +1 -0
  47. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue.js +30 -0
  48. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue.js.map +1 -0
  49. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue2.js +5 -0
  50. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue2.js.map +1 -0
  51. package/dist/components/PlTableFastSearch/index.d.ts +2 -0
  52. package/dist/components/PlTableFastSearch/index.d.ts.map +1 -0
  53. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts +4 -5
  54. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts.map +1 -1
  55. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
  56. package/dist/defineApp.d.ts +11 -11
  57. package/dist/defineApp.d.ts.map +1 -1
  58. package/dist/defineApp.js +90 -58
  59. package/dist/defineApp.js.map +1 -1
  60. package/dist/index.js +59 -55
  61. package/dist/index.js.map +1 -1
  62. package/dist/internal/createAppV3.d.ts +45 -22
  63. package/dist/internal/createAppV3.d.ts.map +1 -1
  64. package/dist/internal/createAppV3.js +103 -70
  65. package/dist/internal/createAppV3.js.map +1 -1
  66. package/dist/lib/util/helpers/dist/functions.js +13 -4
  67. package/dist/lib/util/helpers/dist/functions.js.map +1 -1
  68. package/dist/lib/util/helpers/dist/objects.js.map +1 -1
  69. package/dist/lib.d.ts +1 -0
  70. package/dist/lib.d.ts.map +1 -1
  71. package/dist/types.d.ts +1 -1
  72. package/dist/usePluginData.d.ts +30 -0
  73. package/dist/usePluginData.d.ts.map +1 -0
  74. package/dist/usePluginData.js +22 -0
  75. package/dist/usePluginData.js.map +1 -0
  76. package/package.json +6 -6
  77. package/src/components/PlAdvancedFilter/PlAdvancedFilter.vue +2 -2
  78. package/src/components/PlAdvancedFilter/index.ts +7 -2
  79. package/src/components/PlAdvancedFilter/types.ts +19 -5
  80. package/src/components/PlAgDataTable/PlAgDataTableV2.vue +52 -172
  81. package/src/components/PlAgDataTable/compositions/useFilterableColumns.ts +62 -0
  82. package/src/components/PlAgDataTable/compositions/useGrid.ts +143 -0
  83. package/src/components/PlAgDataTable/sources/row-number.ts +0 -1
  84. package/src/components/PlAgDataTable/sources/table-source-v2.ts +1 -15
  85. package/src/components/PlAgDataTable/sources/table-state-v2.ts +137 -94
  86. package/src/components/PlTableFastSearch/PlTableFastSearch.vue +27 -0
  87. package/src/components/PlTableFastSearch/index.ts +1 -0
  88. package/src/components/PlTableFilters/PlTableFiltersV2.vue +8 -3
  89. package/src/defineApp.ts +116 -87
  90. package/src/internal/createAppV3.ts +84 -12
  91. package/src/internal/v1.static-test.ts +2 -2
  92. package/src/internal/v2.static-test.ts +2 -2
  93. package/src/lib.ts +2 -0
  94. package/src/types.ts +1 -1
  95. package/src/usePluginData.ts +63 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,7 +1,13 @@
1
1
  import { Mutable } from '@milaboratories/helpers';
2
- import { NavigationState, BlockOutputsBase, BlockStateV3, PlatformaV3, ValueWithUTag, AuthorMarker } from '@platforma-sdk/model';
2
+ import { NavigationState, BlockOutputsBase, BlockStateV3, PlatformaV3, ValueWithUTag, AuthorMarker, PlatformaExtended } from '@platforma-sdk/model';
3
3
  import { OutputValues, OutputErrors, AppSettings } from '../types';
4
4
  export declare const patchPoolingDelay = 150;
5
+ /** Internal interface for plugin data access — injected separately from the app. */
6
+ export interface PluginDataAccess {
7
+ readonly pluginDataMap: Record<string, unknown>;
8
+ setPluginData(pluginId: string, value: unknown): Promise<boolean>;
9
+ initPluginDataSlot(pluginId: string): void;
10
+ }
5
11
  export declare const createNextAuthorMarker: (marker: AuthorMarker | undefined) => AuthorMarker;
6
12
  /**
7
13
  * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.
@@ -17,27 +23,44 @@ export declare const createNextAuthorMarker: (marker: AuthorMarker | undefined)
17
23
  *
18
24
  * @returns A reactive application object with methods, getters, and state.
19
25
  */
20
- export declare function createAppV3<Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Data = unknown, Href extends `/${string}` = `/${string}`>(state: ValueWithUTag<BlockStateV3<Outputs, Data, Href>>, platforma: PlatformaV3<Args, Outputs, Data, Href>, settings: AppSettings): {
21
- error: string;
22
- model: {
23
- data: import('vue').UnwrapRef<Data>;
24
- outputs: import('vue').UnwrapRef<OutputValues<Outputs>>;
25
- outputErrors: import('vue').UnwrapRef<OutputErrors<Outputs>>;
26
+ export declare function createAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`>(state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>, platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href>>, settings: AppSettings): {
27
+ app: {
28
+ error: string;
29
+ model: {
30
+ data: import('vue').UnwrapRef<Data>;
31
+ outputs: import('vue').UnwrapRef<OutputValues<Outputs>>;
32
+ outputErrors: import('vue').UnwrapRef<OutputErrors<Outputs>>;
33
+ };
34
+ closedRef: boolean;
35
+ snapshot: {
36
+ outputs: Partial<Outputs>;
37
+ blockStorage: unknown;
38
+ navigationState: NavigationState<Href>;
39
+ };
40
+ queryParams: import('../types').ParseQuery<Href>;
41
+ href: Href;
42
+ hasErrors: boolean;
43
+ } & {
44
+ cloneData: () => Data;
45
+ cloneNavigationState: () => Mutable<NavigationState<Href>>;
46
+ /**
47
+ * Updates the UI state by applying a callback.
48
+ *
49
+ * @param cb - Callback to modify the current UI state.
50
+ * @returns A promise resolving after the update is applied.
51
+ * @todo Make it mutable since there is already an initial one
52
+ */
53
+ updateData(cb: (data: Data) => Data): Promise<boolean>;
54
+ /**
55
+ * Navigates to a specific href by updating the navigation state.
56
+ *
57
+ * @param href - The target href to navigate to.
58
+ * @returns A promise resolving after the navigation state is updated.
59
+ */
60
+ navigateTo(href: Href): Promise<boolean>;
61
+ allSettled(): Promise<void>;
26
62
  };
27
- cloneData: () => Data;
28
- cloneNavigationState: () => Mutable<NavigationState<Href>>;
29
- updateData: (cb: (data: Data) => Data) => Promise<boolean>;
30
- navigateTo: (href: Href) => Promise<boolean>;
31
- allSettled: () => Promise<void>;
32
- closedRef: boolean;
33
- snapshot: {
34
- outputs: Partial<Outputs>;
35
- blockStorage: unknown;
36
- navigationState: NavigationState<Href>;
37
- };
38
- queryParams: import('../types').ParseQuery<Href>;
39
- href: Href;
40
- hasErrors: boolean;
63
+ pluginAccess: PluginDataAccess;
41
64
  };
42
- export type BaseAppV3<Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Data = unknown, Href extends `/${string}` = `/${string}`> = ReturnType<typeof createAppV3<Args, Outputs, Data, Href>>;
65
+ export type BaseAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href>>["app"];
43
66
  //# sourceMappingURL=createAppV3.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createAppV3.d.ts","sourceRoot":"","sources":["../../src/internal/createAppV3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,YAAY,EACb,MAAM,sBAAsB,CAAC;AAI9B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAOxE,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,eAAO,MAAM,sBAAsB,WAAY,YAAY,GAAG,SAAS,KAAG,YAGxE,CAAC;AAUH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,GAAG,OAAO,EACd,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EAExC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EACvD,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EACjD,QAAQ,EAAE,WAAW;WA2FZ,MAAM;;;;;;qBAkF2C,IAAI;gCAEf,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;qBAY5D,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,KAAG,OAAO,CAAC,OAAO,CAAC;uBAYrC,IAAI;;;;iBAnJZ,OAAO,CAAC,OAAO,CAAC;sBACX,OAAO;yBACJ,eAAe,CAAC,IAAI,CAAC;;;;;EA8KzC;AAED,MAAM,MAAM,SAAS,CACnB,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,GAAG,OAAO,EACd,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,IACtC,UAAU,CAAC,OAAO,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"createAppV3.d.ts","sourceRoot":"","sources":["../../src/internal/createAppV3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,YAAY,EACZ,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAU9B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAOxE,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED,eAAO,MAAM,sBAAsB,WAAY,YAAY,GAAG,SAAS,KAAG,YAGxE,CAAC;AAUH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EAExC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACvD,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACpE,QAAQ,EAAE,WAAW;;eA4HZ,MAAM;;;;;;;;qBA5DJ,OAAO,CAAC,OAAO,CAAC;0BACX,OAAO;6BACJ,eAAe,CAAC,IAAI,CAAC;;;;;;yBAgJkB,IAAI;oCAEf,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAK3E;;;;;;WAMG;uBACY,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAMtD;;;;;WAKG;yBACc,IAAI;;;;EAkDxB;AAED,MAAM,MAAM,SAAS,CACnB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,IACtC,UAAU,CAAC,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC"}
@@ -1,101 +1,119 @@
1
- import { delay as $ } from "../lib/util/helpers/dist/utils.js";
2
- import { uniqueId as V } from "../lib/util/helpers/dist/strings.js";
3
- import { deepClone as c } from "../lib/util/helpers/dist/objects.js";
4
- import { deriveDataFromStorage as M, unwrapResult as i, hasAbortError as z } from "@platforma-sdk/model";
5
- import { ref as b, computed as p, reactive as E } from "vue";
6
- import { parseQuery as J } from "../urls.js";
7
- import { MultiError as L } from "../utils.js";
8
- import { applyPatch as I } from "fast-json-patch";
1
+ import { delay as L } from "../lib/util/helpers/dist/utils.js";
2
+ import { uniqueId as R } from "../lib/util/helpers/dist/strings.js";
3
+ import { deepClone as h } from "../lib/util/helpers/dist/objects.js";
4
+ import { deriveDataFromStorage as N, unwrapResult as p, hasAbortError as G, normalizeBlockStorage as K, getPluginData as X } from "@platforma-sdk/model";
5
+ import { ref as D, reactive as y, computed as g } from "vue";
6
+ import { parseQuery as Y } from "../urls.js";
7
+ import { ensureOutputHasStableFlag as Z, MultiError as W } from "../utils.js";
8
+ import { applyPatch as V } from "fast-json-patch";
9
9
  import { UpdateSerializer as P } from "./UpdateSerializer.js";
10
- import { watchIgnorable as k } from "@vueuse/core";
11
- const j = 150, B = (n) => ({
12
- authorId: (n == null ? void 0 : n.authorId) ?? V(),
13
- localVersion: ((n == null ? void 0 : n.localVersion) ?? 0) + 1
14
- }), N = (n) => {
10
+ import { watchIgnorable as ee } from "@vueuse/core";
11
+ const _ = 150, te = (r) => ({
12
+ authorId: (r == null ? void 0 : r.authorId) ?? R(),
13
+ localVersion: ((r == null ? void 0 : r.localVersion) ?? 0) + 1
14
+ }), F = (r) => {
15
15
  try {
16
- return JSON.stringify(n, null, 2);
16
+ return JSON.stringify(r, null, 2);
17
17
  } catch (u) {
18
18
  return u instanceof Error ? u.message : String(u);
19
19
  }
20
20
  };
21
- function oe(n, u, g) {
22
- const r = (e, ...a) => {
23
- g.debug && console.log(
21
+ function de(r, u, f) {
22
+ const n = (e, ...t) => {
23
+ f.debug && console.log(
24
24
  `%c>>> %c${e}`,
25
25
  "color: orange; font-weight: bold",
26
26
  "color: orange",
27
- ...a.map((t) => N(t))
27
+ ...t.map((a) => F(a))
28
28
  );
29
- }, w = (e, ...a) => {
29
+ }, M = (e, ...t) => {
30
30
  console.error(
31
31
  `%c>>> %c${e}`,
32
32
  "color: red; font-weight: bold",
33
33
  "color: red",
34
- ...a.map((t) => N(t))
34
+ ...t.map((a) => F(a))
35
35
  );
36
36
  }, s = {
37
37
  isExternalSnapshot: !1,
38
38
  author: {
39
- authorId: V(),
39
+ authorId: R(),
40
40
  localVersion: 0
41
41
  }
42
- }, _ = () => (s.author = B(s.author), r("nextAuthorMarker", s.author), s.author), d = b(!1), m = b(n.uTag), S = g.debounceSpan ?? 200, v = new P({ debounceSpan: S }), Q = new P({ debounceSpan: S }), o = b(n.value), y = async (e) => u.mutateStorage({ operation: "update-data", value: e }, _()), R = async (e) => u.setNavigationState(e), O = p(() => {
42
+ }, T = () => (s.author = te(s.author), n("nextAuthorMarker", s.author), s.author), m = D(!1), v = D(r.uTag), b = f.debounceSpan ?? 200, S = new P({ debounceSpan: b }), w = /* @__PURE__ */ new Map(), k = (e) => {
43
+ let t = w.get(e);
44
+ return t || (t = new P({ debounceSpan: b }), w.set(e, t)), t;
45
+ }, q = new P({ debounceSpan: b }), c = y({}), o = D(r.value), A = async (e) => u.mutateStorage({ operation: "update-block-data", value: e }, T()), I = async (e, t) => u.mutateStorage(
46
+ { operation: "update-plugin-data", pluginId: e, value: t },
47
+ T()
48
+ ), E = (e) => {
49
+ const t = K(o.value.blockStorage);
50
+ return X(t, e);
51
+ }, z = async (e) => u.setNavigationState(e), C = g(() => {
43
52
  const e = Object.entries(o.value.outputs).map(
44
- ([a, t]) => [a, t.ok && t.value !== void 0 ? t.value : void 0]
53
+ ([t, a]) => {
54
+ var l;
55
+ return (l = u.blockModelInfo.outputs[t]) != null && l.withStatus ? [t, Z(a)] : [
56
+ t,
57
+ a.ok && a.value !== void 0 ? a.value : void 0
58
+ ];
59
+ }
45
60
  );
46
61
  return Object.fromEntries(e);
47
- }), q = p(() => {
62
+ }), U = g(() => {
48
63
  const e = Object.entries(o.value.outputs).map(
49
- ([a, t]) => [
50
- a,
51
- t && t.ok === !1 ? new L(t.errors) : void 0
64
+ ([t, a]) => [
65
+ t,
66
+ a && a.ok === !1 ? new W(a.errors) : void 0
52
67
  ]
53
68
  );
54
69
  return Object.fromEntries(e);
55
- }), l = E({
70
+ }), d = y({
56
71
  apiVersion: 3,
57
72
  error: "",
58
73
  model: {
59
- data: c(M(o.value.blockStorage)),
60
- outputs: O,
61
- outputErrors: q
74
+ data: h(N(o.value.blockStorage)),
75
+ outputs: C,
76
+ outputErrors: U
62
77
  }
63
- }), { ignoreUpdates: D } = k(
64
- () => l.model,
78
+ }), { ignoreUpdates: j } = ee(
79
+ () => d.model,
65
80
  (e) => {
66
- const a = c(e);
67
- r("setDataQueue appModel.model, data", a.data), v.run(() => y(a.data).then(i));
81
+ const t = h(e);
82
+ n("setDataQueue appModel.model, data", t.data), S.run(() => A(t.data).then(p));
68
83
  },
69
84
  { deep: !0 }
70
- ), C = (e) => {
71
- r("updateAppModel", e), l.model.data = c(e.data);
85
+ ), $ = (e) => {
86
+ n("updateAppModel", e), d.model.data = h(e.data);
72
87
  };
73
88
  (async () => {
74
- var e, a;
89
+ var e, t;
75
90
  for (window.addEventListener("beforeunload", () => {
76
- d.value = !0, u.dispose().then(i).catch((t) => {
77
- w("error in dispose", t);
91
+ m.value = !0, u.dispose().then(p).catch((a) => {
92
+ M("error in dispose", a);
78
93
  });
79
- }); !d.value; )
94
+ }); !m.value; )
80
95
  try {
81
- const t = await u.getPatches(m.value).then(i);
82
- if (r("patches.length", t.value.length), r("uTagRef.value", m.value), r("patches.uTag", t.uTag), r("patches.author", t.author), r("data.author", s.author), m.value = t.uTag, t.value.length === 0) {
83
- await new Promise((f) => setTimeout(f, j));
96
+ const a = await u.getPatches(v.value).then(p);
97
+ if (n("patches.length", a.value.length), n("uTagRef.value", v.value), n("patches.uTag", a.uTag), n("patches.author", a.author), n("data.author", s.author), v.value = a.uTag, a.value.length === 0) {
98
+ await new Promise((i) => setTimeout(i, _));
84
99
  continue;
85
100
  }
86
- const h = ((e = s.author) == null ? void 0 : e.authorId) !== ((a = t.author) == null ? void 0 : a.authorId);
87
- h || s.isExternalSnapshot ? (r("got external changes, applying them to the snapshot", t.value), D(() => {
88
- o.value = I(o.value, t.value, !1, !1).newDocument, C({ data: M(o.value.blockStorage) }), s.isExternalSnapshot = h;
89
- })) : (r("outputs changed", t.value), D(() => {
90
- o.value = I(o.value, t.value).newDocument;
91
- })), await new Promise((f) => setTimeout(f, j));
92
- } catch (t) {
93
- z(t) ? (r("patches loop aborted"), d.value = !0) : (w("error in patches loop", t), await new Promise((h) => setTimeout(h, 1e3)));
101
+ const l = ((e = s.author) == null ? void 0 : e.authorId) !== ((t = a.author) == null ? void 0 : t.authorId);
102
+ l || s.isExternalSnapshot ? (n("got external changes, applying them to the snapshot", a.value), j(() => {
103
+ o.value = V(o.value, a.value, !1, !1).newDocument, $({ data: N(o.value.blockStorage) });
104
+ for (const i of Object.keys(c))
105
+ c[i] = E(i);
106
+ s.isExternalSnapshot = l;
107
+ })) : (n("outputs changed", a.value), j(() => {
108
+ o.value = V(o.value, a.value).newDocument;
109
+ })), await new Promise((i) => setTimeout(i, _));
110
+ } catch (a) {
111
+ G(a) ? (n("patches loop aborted"), m.value = !0) : (M("error in patches loop", a), await new Promise((l) => setTimeout(l, 1e3)));
94
112
  }
95
113
  })();
96
- const T = () => c(l.model.data), x = () => c(o.value.navigationState), F = {
97
- cloneData: T,
98
- cloneNavigationState: x,
114
+ const x = () => h(d.model.data), O = () => h(o.value.navigationState), B = {
115
+ cloneData: x,
116
+ cloneNavigationState: O,
99
117
  /**
100
118
  * Updates the UI state by applying a callback.
101
119
  *
@@ -104,8 +122,8 @@ function oe(n, u, g) {
104
122
  * @todo Make it mutable since there is already an initial one
105
123
  */
106
124
  updateData(e) {
107
- const a = e(T());
108
- return r("updateData", a), l.model.data = a, v.run(() => y(a).then(i));
125
+ const t = e(x());
126
+ return n("updateData", t), d.model.data = t, S.run(() => A(t).then(p));
109
127
  },
110
128
  /**
111
129
  * Navigates to a specific href by updating the navigation state.
@@ -114,26 +132,41 @@ function oe(n, u, g) {
114
132
  * @returns A promise resolving after the navigation state is updated.
115
133
  */
116
134
  navigateTo(e) {
117
- const a = x();
118
- return a.href = e, Q.run(() => R(a).then(i));
135
+ const t = O();
136
+ return t.href = e, q.run(() => z(t).then(p));
119
137
  },
120
138
  async allSettled() {
121
- return await $(0), v.allSettled();
139
+ await L(0);
140
+ const e = [
141
+ S.allSettled(),
142
+ ...Array.from(w.values()).map((t) => t.allSettled())
143
+ ];
144
+ await Promise.all(e);
145
+ }
146
+ }, H = {
147
+ pluginDataMap: c,
148
+ setPluginData(e, t) {
149
+ return c[e] = t, n("setPluginData", e, t), k(e).run(
150
+ () => I(e, t).then(p)
151
+ );
152
+ },
153
+ initPluginDataSlot(e) {
154
+ e in c || (c[e] = E(e));
122
155
  }
123
- }, U = {
124
- closedRef: d,
156
+ }, J = {
157
+ closedRef: m,
125
158
  snapshot: o,
126
- queryParams: p(() => J(o.value.navigationState.href)),
127
- href: p(() => o.value.navigationState.href),
128
- hasErrors: p(
159
+ queryParams: g(() => Y(o.value.navigationState.href)),
160
+ href: g(() => o.value.navigationState.href),
161
+ hasErrors: g(
129
162
  () => Object.values(o.value.outputs).some((e) => !(e != null && e.ok))
130
163
  )
131
- }, A = E(Object.assign(l, F, U));
132
- return g.debug && (globalThis.__block_app__ = A), A;
164
+ }, Q = Object.assign(y(Object.assign(d, J)), B);
165
+ return f.debug && (globalThis.__block_app__ = Q), { app: Q, pluginAccess: H };
133
166
  }
134
167
  export {
135
- oe as createAppV3,
136
- B as createNextAuthorMarker,
137
- j as patchPoolingDelay
168
+ de as createAppV3,
169
+ te as createNextAuthorMarker,
170
+ _ as patchPoolingDelay
138
171
  };
139
172
  //# sourceMappingURL=createAppV3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createAppV3.js","sources":["../../src/internal/createAppV3.ts"],"sourcesContent":["import { deepClone, delay, uniqueId } from \"@milaboratories/helpers\";\nimport type { Mutable } from \"@milaboratories/helpers\";\nimport type {\n NavigationState,\n BlockOutputsBase,\n BlockStateV3,\n PlatformaV3,\n ValueWithUTag,\n AuthorMarker,\n} from \"@platforma-sdk/model\";\nimport { hasAbortError, unwrapResult, deriveDataFromStorage } from \"@platforma-sdk/model\";\nimport type { Ref } from \"vue\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { OutputValues, OutputErrors, AppSettings } from \"../types\";\nimport { parseQuery } from \"../urls\";\nimport { MultiError } from \"../utils\";\nimport { applyPatch } from \"fast-json-patch\";\nimport { UpdateSerializer } from \"./UpdateSerializer\";\nimport { watchIgnorable } from \"@vueuse/core\";\n\nexport const patchPoolingDelay = 150;\n\nexport const createNextAuthorMarker = (marker: AuthorMarker | undefined): AuthorMarker => ({\n authorId: marker?.authorId ?? uniqueId(),\n localVersion: (marker?.localVersion ?? 0) + 1,\n});\n\nconst stringifyForDebug = (v: unknown) => {\n try {\n return JSON.stringify(v, null, 2);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n};\n\n/**\n * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.\n *\n * @template Args - The type of arguments used in the application.\n * @template Outputs - The type of block outputs extending `BlockOutputsBase`.\n * @template Data - The type of the block data.\n * @template Href - The type of navigation href, defaulting to a string starting with `/`.\n *\n * @param state - Initial state of the application, including args, outputs, UI state, and navigation state.\n * @param platforma - A platform interface for interacting with block states.\n * @param settings - Application settings, such as debug flags.\n *\n * @returns A reactive application object with methods, getters, and state.\n */\nexport function createAppV3<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Data = unknown,\n Href extends `/${string}` = `/${string}`,\n>(\n state: ValueWithUTag<BlockStateV3<Outputs, Data, Href>>,\n platforma: PlatformaV3<Args, Outputs, Data, Href>,\n settings: AppSettings,\n) {\n const debug = (msg: string, ...rest: unknown[]) => {\n if (settings.debug) {\n console.log(\n `%c>>> %c${msg}`,\n \"color: orange; font-weight: bold\",\n \"color: orange\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n }\n };\n\n const error = (msg: string, ...rest: unknown[]) => {\n console.error(\n `%c>>> %c${msg}`,\n \"color: red; font-weight: bold\",\n \"color: red\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n };\n\n const data = {\n isExternalSnapshot: false,\n author: {\n authorId: uniqueId(),\n localVersion: 0,\n },\n };\n\n const nextAuthorMarker = () => {\n data.author = createNextAuthorMarker(data.author);\n debug(\"nextAuthorMarker\", data.author);\n return data.author;\n };\n\n const closedRef = ref(false);\n\n const uTagRef = ref(state.uTag);\n\n const debounceSpan = settings.debounceSpan ?? 200;\n\n const setDataQueue = new UpdateSerializer({ debounceSpan });\n const setNavigationStateQueue = new UpdateSerializer({ debounceSpan });\n /**\n * Reactive snapshot of the application state, including args, outputs, UI state, and navigation state.\n */\n const snapshot = ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>(state.value) as Ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>;\n\n const updateData = async (value: Data) => {\n return platforma.mutateStorage({ operation: \"update-data\", value }, nextAuthorMarker());\n };\n\n const setNavigationState = async (state: NavigationState<Href>) => {\n return platforma.setNavigationState(state);\n };\n\n const outputs = computed<OutputValues<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>).map(\n ([k, vOrErr]) => [k, vOrErr.ok && vOrErr.value !== undefined ? vOrErr.value : undefined],\n );\n return Object.fromEntries(entries);\n });\n\n const outputErrors = computed<OutputErrors<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>).map(\n ([k, vOrErr]) => [\n k,\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const appModel = reactive({\n apiVersion: 3,\n error: \"\",\n model: {\n data: deepClone(deriveDataFromStorage<Data>(snapshot.value.blockStorage)) as Data,\n outputs,\n outputErrors,\n },\n }) as {\n error: string;\n model: {\n data: Data;\n outputs: OutputValues<Outputs>;\n outputErrors: OutputErrors<Outputs>;\n };\n };\n\n const { ignoreUpdates } = watchIgnorable(\n () => appModel.model,\n (_newData) => {\n const newData = deepClone(_newData);\n debug(\"setDataQueue appModel.model, data\", newData.data);\n setDataQueue.run(() => updateData(newData.data).then(unwrapResult));\n },\n { deep: true },\n );\n\n const updateAppModel = (newData: { data: Data }) => {\n debug(\"updateAppModel\", newData);\n appModel.model.data = deepClone(newData.data) as Data;\n };\n\n (async () => {\n window.addEventListener(\"beforeunload\", () => {\n closedRef.value = true;\n platforma\n .dispose()\n .then(unwrapResult)\n .catch((err) => {\n error(\"error in dispose\", err);\n });\n });\n\n while (!closedRef.value) {\n try {\n const patches = await platforma.getPatches(uTagRef.value).then(unwrapResult);\n\n debug(\"patches.length\", patches.value.length);\n debug(\"uTagRef.value\", uTagRef.value);\n debug(\"patches.uTag\", patches.uTag);\n debug(\"patches.author\", patches.author);\n debug(\"data.author\", data.author);\n\n uTagRef.value = patches.uTag;\n\n if (patches.value.length === 0) {\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n continue;\n }\n\n const isAuthorChanged = data.author?.authorId !== patches.author?.authorId;\n\n // Immutable behavior, apply external changes to the snapshot\n if (isAuthorChanged || data.isExternalSnapshot) {\n debug(\"got external changes, applying them to the snapshot\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value, false, false).newDocument;\n updateAppModel({ data: deriveDataFromStorage<Data>(snapshot.value.blockStorage) });\n data.isExternalSnapshot = isAuthorChanged;\n });\n } else {\n // Mutable behavior\n debug(\"outputs changed\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value).newDocument;\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n } catch (err) {\n if (hasAbortError(err)) {\n debug(\"patches loop aborted\");\n closedRef.value = true;\n } else {\n error(\"error in patches loop\", err);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n })();\n\n const cloneData = () => deepClone(appModel.model.data) as Data;\n const cloneNavigationState = () =>\n deepClone(snapshot.value.navigationState) as Mutable<NavigationState<Href>>;\n\n const methods = {\n cloneData,\n cloneNavigationState,\n /**\n * Updates the UI state by applying a callback.\n *\n * @param cb - Callback to modify the current UI state.\n * @returns A promise resolving after the update is applied.\n * @todo Make it mutable since there is already an initial one\n */\n updateData(cb: (data: Data) => Data): Promise<boolean> {\n const newData = cb(cloneData());\n debug(\"updateData\", newData);\n appModel.model.data = newData;\n return setDataQueue.run(() => updateData(newData).then(unwrapResult));\n },\n /**\n * Navigates to a specific href by updating the navigation state.\n *\n * @param href - The target href to navigate to.\n * @returns A promise resolving after the navigation state is updated.\n */\n navigateTo(href: Href) {\n const newState = cloneNavigationState();\n newState.href = href;\n return setNavigationStateQueue.run(() => setNavigationState(newState).then(unwrapResult));\n },\n async allSettled() {\n await delay(0);\n return setDataQueue.allSettled();\n },\n };\n\n const getters = {\n closedRef,\n snapshot,\n queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),\n href: computed(() => snapshot.value.navigationState.href),\n hasErrors: computed(() =>\n Object.values(snapshot.value.outputs as Partial<Readonly<Outputs>>).some((v) => !v?.ok),\n ),\n };\n\n const app = reactive(Object.assign(appModel, methods, getters));\n\n if (settings.debug) {\n // @ts-expect-error (to inspect in console in debug mode)\n globalThis.__block_app__ = app;\n }\n\n return app;\n}\n\nexport type BaseAppV3<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Data = unknown,\n Href extends `/${string}` = `/${string}`,\n> = ReturnType<typeof createAppV3<Args, Outputs, Data, Href>>;\n"],"names":["patchPoolingDelay","createNextAuthorMarker","marker","uniqueId","stringifyForDebug","v","err","createAppV3","state","platforma","settings","debug","msg","rest","r","error","data","nextAuthorMarker","closedRef","ref","uTagRef","debounceSpan","setDataQueue","UpdateSerializer","setNavigationStateQueue","snapshot","updateData","value","setNavigationState","outputs","computed","entries","k","vOrErr","outputErrors","MultiError","appModel","reactive","deepClone","deriveDataFromStorage","ignoreUpdates","watchIgnorable","_newData","newData","unwrapResult","updateAppModel","patches","resolve","isAuthorChanged","_a","_b","applyPatch","hasAbortError","cloneData","cloneNavigationState","methods","cb","href","newState","delay","getters","parseQuery","app"],"mappings":"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"}
1
+ {"version":3,"file":"createAppV3.js","sources":["../../src/internal/createAppV3.ts"],"sourcesContent":["import { deepClone, delay, uniqueId } from \"@milaboratories/helpers\";\nimport type { Mutable } from \"@milaboratories/helpers\";\nimport type {\n NavigationState,\n BlockOutputsBase,\n BlockStateV3,\n PlatformaV3,\n ValueWithUTag,\n AuthorMarker,\n PlatformaExtended,\n} from \"@platforma-sdk/model\";\nimport {\n hasAbortError,\n unwrapResult,\n deriveDataFromStorage,\n getPluginData,\n normalizeBlockStorage,\n} from \"@platforma-sdk/model\";\nimport type { Ref } from \"vue\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { OutputValues, OutputErrors, AppSettings } from \"../types\";\nimport { parseQuery } from \"../urls\";\nimport { ensureOutputHasStableFlag, MultiError } from \"../utils\";\nimport { applyPatch } from \"fast-json-patch\";\nimport { UpdateSerializer } from \"./UpdateSerializer\";\nimport { watchIgnorable } from \"@vueuse/core\";\n\nexport const patchPoolingDelay = 150;\n\n/** Internal interface for plugin data access — injected separately from the app. */\nexport interface PluginDataAccess {\n readonly pluginDataMap: Record<string, unknown>;\n setPluginData(pluginId: string, value: unknown): Promise<boolean>;\n initPluginDataSlot(pluginId: string): void;\n}\n\nexport const createNextAuthorMarker = (marker: AuthorMarker | undefined): AuthorMarker => ({\n authorId: marker?.authorId ?? uniqueId(),\n localVersion: (marker?.localVersion ?? 0) + 1,\n});\n\nconst stringifyForDebug = (v: unknown) => {\n try {\n return JSON.stringify(v, null, 2);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n};\n\n/**\n * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.\n *\n * @template Args - The type of arguments used in the application.\n * @template Outputs - The type of block outputs extending `BlockOutputsBase`.\n * @template Data - The type of the block data.\n * @template Href - The type of navigation href, defaulting to a string starting with `/`.\n *\n * @param state - Initial state of the application, including args, outputs, UI state, and navigation state.\n * @param platforma - A platform interface for interacting with block states.\n * @param settings - Application settings, such as debug flags.\n *\n * @returns A reactive application object with methods, getters, and state.\n */\nexport function createAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n>(\n state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>,\n platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href>>,\n settings: AppSettings,\n) {\n const debug = (msg: string, ...rest: unknown[]) => {\n if (settings.debug) {\n console.log(\n `%c>>> %c${msg}`,\n \"color: orange; font-weight: bold\",\n \"color: orange\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n }\n };\n\n const error = (msg: string, ...rest: unknown[]) => {\n console.error(\n `%c>>> %c${msg}`,\n \"color: red; font-weight: bold\",\n \"color: red\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n };\n\n const data = {\n isExternalSnapshot: false,\n author: {\n authorId: uniqueId(),\n localVersion: 0,\n },\n };\n\n const nextAuthorMarker = () => {\n data.author = createNextAuthorMarker(data.author);\n debug(\"nextAuthorMarker\", data.author);\n return data.author;\n };\n\n const closedRef = ref(false);\n\n const uTagRef = ref(state.uTag);\n\n const debounceSpan = settings.debounceSpan ?? 200;\n\n const setDataQueue = new UpdateSerializer({ debounceSpan });\n const pluginDataQueues = new Map<string, UpdateSerializer>();\n const getPluginDataQueue = (pluginId: string): UpdateSerializer => {\n let queue = pluginDataQueues.get(pluginId);\n if (!queue) {\n queue = new UpdateSerializer({ debounceSpan });\n pluginDataQueues.set(pluginId, queue);\n }\n return queue;\n };\n const setNavigationStateQueue = new UpdateSerializer({ debounceSpan });\n\n /** Reactive map of plugin data keyed by pluginId. Optimistic state for plugin components. */\n const pluginDataMap = reactive<Record<string, unknown>>({});\n /**\n * Reactive snapshot of the application state, including args, outputs, UI state, and navigation state.\n */\n const snapshot = ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>(state.value) as Ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>;\n\n const updateData = async (value: Data) => {\n return platforma.mutateStorage({ operation: \"update-block-data\", value }, nextAuthorMarker());\n };\n\n const updatePluginData = async (pluginId: string, value: unknown) => {\n return platforma.mutateStorage(\n { operation: \"update-plugin-data\", pluginId, value },\n nextAuthorMarker(),\n );\n };\n\n /** Derives plugin data for a given pluginId from the current snapshot. */\n const derivePluginDataFromSnapshot = (pluginId: string): unknown => {\n const storage = normalizeBlockStorage(snapshot.value.blockStorage);\n return getPluginData(storage, pluginId);\n };\n\n const setNavigationState = async (state: NavigationState<Href>) => {\n return platforma.setNavigationState(state);\n };\n\n const outputs = computed<OutputValues<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>).map(\n ([k, outputWithStatus]) =>\n platforma.blockModelInfo.outputs[k]?.withStatus\n ? [k, ensureOutputHasStableFlag(outputWithStatus)]\n : [\n k,\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const outputErrors = computed<OutputErrors<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>).map(\n ([k, vOrErr]) => [\n k,\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const appModel = reactive({\n apiVersion: 3,\n error: \"\",\n model: {\n data: deepClone(deriveDataFromStorage<Data>(snapshot.value.blockStorage)) as Data,\n outputs,\n outputErrors,\n },\n }) as {\n error: string;\n model: {\n data: Data;\n outputs: OutputValues<Outputs>;\n outputErrors: OutputErrors<Outputs>;\n };\n };\n\n const { ignoreUpdates } = watchIgnorable(\n () => appModel.model,\n (_newData) => {\n const newData = deepClone(_newData);\n debug(\"setDataQueue appModel.model, data\", newData.data);\n setDataQueue.run(() => updateData(newData.data).then(unwrapResult));\n },\n { deep: true },\n );\n\n const updateAppModel = (newData: { data: Data }) => {\n debug(\"updateAppModel\", newData);\n appModel.model.data = deepClone(newData.data) as Data;\n };\n\n (async () => {\n window.addEventListener(\"beforeunload\", () => {\n closedRef.value = true;\n platforma\n .dispose()\n .then(unwrapResult)\n .catch((err) => {\n error(\"error in dispose\", err);\n });\n });\n\n while (!closedRef.value) {\n try {\n const patches = await platforma.getPatches(uTagRef.value).then(unwrapResult);\n\n debug(\"patches.length\", patches.value.length);\n debug(\"uTagRef.value\", uTagRef.value);\n debug(\"patches.uTag\", patches.uTag);\n debug(\"patches.author\", patches.author);\n debug(\"data.author\", data.author);\n\n uTagRef.value = patches.uTag;\n\n if (patches.value.length === 0) {\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n continue;\n }\n\n const isAuthorChanged = data.author?.authorId !== patches.author?.authorId;\n\n // Immutable behavior, apply external changes to the snapshot\n if (isAuthorChanged || data.isExternalSnapshot) {\n debug(\"got external changes, applying them to the snapshot\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value, false, false).newDocument;\n updateAppModel({ data: deriveDataFromStorage<Data>(snapshot.value.blockStorage) });\n // Reconcile plugin data from external source\n for (const pluginId of Object.keys(pluginDataMap)) {\n pluginDataMap[pluginId] = derivePluginDataFromSnapshot(pluginId);\n }\n data.isExternalSnapshot = isAuthorChanged;\n });\n } else {\n // Mutable behavior\n debug(\"outputs changed\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value).newDocument;\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n } catch (err) {\n if (hasAbortError(err)) {\n debug(\"patches loop aborted\");\n closedRef.value = true;\n } else {\n error(\"error in patches loop\", err);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n })();\n\n const cloneData = () => deepClone(appModel.model.data) as Data;\n const cloneNavigationState = () =>\n deepClone(snapshot.value.navigationState) as Mutable<NavigationState<Href>>;\n\n const methods = {\n cloneData,\n cloneNavigationState,\n /**\n * Updates the UI state by applying a callback.\n *\n * @param cb - Callback to modify the current UI state.\n * @returns A promise resolving after the update is applied.\n * @todo Make it mutable since there is already an initial one\n */\n updateData(cb: (data: Data) => Data): Promise<boolean> {\n const newData = cb(cloneData());\n debug(\"updateData\", newData);\n appModel.model.data = newData;\n return setDataQueue.run(() => updateData(newData).then(unwrapResult));\n },\n /**\n * Navigates to a specific href by updating the navigation state.\n *\n * @param href - The target href to navigate to.\n * @returns A promise resolving after the navigation state is updated.\n */\n navigateTo(href: Href) {\n const newState = cloneNavigationState();\n newState.href = href;\n return setNavigationStateQueue.run(() => setNavigationState(newState).then(unwrapResult));\n },\n async allSettled() {\n await delay(0);\n const allQueues = [\n setDataQueue.allSettled(),\n ...Array.from(pluginDataQueues.values()).map((q) => q.allSettled()),\n ];\n await Promise.all(allQueues);\n },\n };\n\n /** Plugin internals — provided via separate injection key, not exposed on useApp(). */\n const pluginAccess: PluginDataAccess = {\n pluginDataMap,\n setPluginData(pluginId: string, value: unknown): Promise<boolean> {\n pluginDataMap[pluginId] = value;\n debug(\"setPluginData\", pluginId, value);\n return getPluginDataQueue(pluginId).run(() =>\n updatePluginData(pluginId, value).then(unwrapResult),\n );\n },\n initPluginDataSlot(pluginId: string): void {\n if (!(pluginId in pluginDataMap)) {\n pluginDataMap[pluginId] = derivePluginDataFromSnapshot(pluginId);\n }\n },\n };\n\n const getters = {\n closedRef,\n snapshot,\n queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),\n href: computed(() => snapshot.value.navigationState.href),\n hasErrors: computed(() =>\n Object.values(snapshot.value.outputs as Partial<Readonly<Outputs>>).some((v) => !v?.ok),\n ),\n };\n\n const app = Object.assign(reactive(Object.assign(appModel, getters)), methods);\n\n if (settings.debug) {\n // @ts-expect-error (to inspect in console in debug mode)\n globalThis.__block_app__ = app;\n }\n\n return { app, pluginAccess };\n}\n\nexport type BaseAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href>>[\"app\"];\n"],"names":["patchPoolingDelay","createNextAuthorMarker","marker","uniqueId","stringifyForDebug","v","err","createAppV3","state","platforma","settings","debug","msg","rest","r","error","data","nextAuthorMarker","closedRef","ref","uTagRef","debounceSpan","setDataQueue","UpdateSerializer","pluginDataQueues","getPluginDataQueue","pluginId","queue","setNavigationStateQueue","pluginDataMap","reactive","snapshot","updateData","value","updatePluginData","derivePluginDataFromSnapshot","storage","normalizeBlockStorage","getPluginData","setNavigationState","outputs","computed","entries","k","outputWithStatus","_a","ensureOutputHasStableFlag","outputErrors","vOrErr","MultiError","appModel","deepClone","deriveDataFromStorage","ignoreUpdates","watchIgnorable","_newData","newData","unwrapResult","updateAppModel","patches","resolve","isAuthorChanged","_b","applyPatch","hasAbortError","cloneData","cloneNavigationState","methods","cb","href","newState","delay","allQueues","q","pluginAccess","getters","parseQuery","app"],"mappings":"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"}
@@ -1,10 +1,19 @@
1
- function t(r, e) {
1
+ function u(i, t) {
2
2
  return Promise.race([
3
- r,
4
- new Promise((i, o) => setTimeout(() => o(Error(`Timeout exceeded ${e}`)), e))
3
+ i,
4
+ new Promise((o, e) => setTimeout(() => e(Error(`Timeout exceeded ${t}`)), t))
5
5
  ]);
6
6
  }
7
+ function n(i, t, o) {
8
+ let e;
9
+ return function(...r) {
10
+ e && clearTimeout(e), e = setTimeout(() => {
11
+ e = void 0, i.apply(this, r);
12
+ }, t);
13
+ };
14
+ }
7
15
  export {
8
- t as promiseTimeout
16
+ n as debounce,
17
+ u as promiseTimeout
9
18
  };
10
19
  //# sourceMappingURL=functions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"functions.js","sources":["../../../../../../../lib/util/helpers/src/functions.ts"],"sourcesContent":["import type { AnyFunction } from \"./types\";\n\nexport function isFunction(value: unknown): value is AnyFunction {\n return typeof value === \"function\";\n}\n\n/**\n * A utility class that ensures asynchronous locks, allowing only one task to proceed at a time.\n */\nexport class AwaitLock {\n private acquired = false;\n private resolvers: (() => void)[] = [];\n\n acquireAsync(): Promise<void> {\n if (!this.acquired) {\n this.acquired = true;\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n this.resolvers.push(resolve);\n });\n }\n\n release(): void {\n if (!this.acquired) {\n throw new Error(\"Cannot release not acquired lock\");\n }\n\n if (this.resolvers.length) {\n this.resolvers.shift()?.();\n } else {\n this.acquired = false;\n }\n }\n}\n\n/**\n * A utility to add a timeout to a promise, rejecting the promise if the timeout is exceeded.\n */\nexport function promiseTimeout<T>(prom: PromiseLike<T>, ms: number): Promise<T> {\n return Promise.race<T>([\n prom,\n new Promise((_r, reject) => setTimeout(() => reject(Error(`Timeout exceeded ${ms}`)), ms)),\n ]);\n}\n\n/**\n * Debounce utility: delays the execution of a function until a certain time has passed since the last call.\n * @param callback\n * @param ms\n * @param immediate (if first call is required)\n * @returns\n */\nexport function debounce<F extends AnyFunction>(\n callback: F,\n ms: number,\n immediate?: boolean,\n): (...args: Parameters<F>) => void {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n return function (this: unknown, ...args: Parameters<F>) {\n const i = immediate && !timeout;\n if (i) {\n callback.apply(this, args);\n }\n if (timeout) {\n clearTimeout(timeout);\n }\n timeout = setTimeout(() => {\n timeout = undefined;\n if (!i) {\n callback.apply(this, args);\n }\n }, ms);\n };\n}\n\n/**\n * Throttle utility: ensures a function is called at most once every `ms` milliseconds.\n * @param callback\n * @param ms milliseconds\n * @param trailing (ensure last call)\n * @returns\n */\nexport function throttle<F extends AnyFunction>(\n callback: F,\n ms: number,\n trailing = true,\n): (...args: Parameters<F>) => void {\n let t = 0,\n call: AnyFunction | null;\n return function (this: unknown, ...args: Parameters<F>) {\n call = () => {\n callback.apply(this, args);\n t = new Date().getTime() + ms;\n call = null;\n if (trailing) {\n setTimeout(() => {\n call?.();\n }, ms);\n }\n };\n if (new Date().getTime() > t) call();\n };\n}\n\n/**\n * Memoization utility: caches results of function calls based on their arguments to avoid redundant calculations.\n */\nexport const memoize = <F extends AnyFunction>(fn: F) => {\n const cache = new Map();\n return function (...args: Parameters<F>): ReturnType<F> {\n const key = JSON.stringify(args);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return cache.has(key)\n ? cache.get(key)\n : cache.set(key, fn.call(null, ...args)) && cache.get(key);\n };\n};\n\n/**\n * Function wrapper utility: executes a function before the main function is called.\n */\nexport const wrapFunction = <T extends unknown[], U>(fn: (...args: T) => U, before: () => void) => {\n return (...args: T): U => {\n before();\n return fn(...args);\n };\n};\n\n/**\n * Function piping utility: allows chaining of functions by passing the result of one as input to another\n */\nexport function pipe<A, B>(cb: (a: A) => B) {\n const fn = (a: A) => cb(a);\n\n fn.pipe = <C>(next: (b: B) => C) => pipe((a: A) => next(cb(a)));\n\n return fn;\n}\n\n/**\n * Ensures that only one request can be processed at a time.\n */\nexport function exclusiveRequest<A, R>(request: (...args: A[]) => Promise<R>) {\n let counter = 0n;\n let ongoingOperation: Promise<R> | undefined;\n\n return async function (...params: A[]): Promise<\n | {\n ok: false;\n }\n | {\n ok: true;\n value: R;\n }\n > {\n const myId = ++counter;\n\n try {\n await ongoingOperation;\n } catch {\n // ignoring the error here, original caller will receive any rejections\n }\n\n // checking that this update is still the most recent\n if (counter !== myId) {\n return {\n ok: false,\n };\n }\n\n const promise = request(...params);\n\n ongoingOperation = promise;\n\n const value = await promise;\n\n return {\n ok: true,\n value,\n };\n };\n}\n\nexport function tryDo<R1>(fn: () => R1): R1 | undefined;\nexport function tryDo<R1, R2>(fn: () => R1, fallback: (cause: unknown) => R2): R1 | R2;\nexport function tryDo(fn: () => unknown, fallback?: (cause: unknown) => unknown) {\n try {\n return fn();\n } catch (cause: unknown) {\n return fallback?.(cause);\n }\n}\n"],"names":["promiseTimeout","prom","ms","_r","reject"],"mappings":"AAwCM,SAAUA,EAAkBC,GAAsBC,GAAU;AAChE,SAAO,QAAQ,KAAQ;AAAA,IACrBD;AAAA,IACA,IAAI,QAAQ,CAACE,GAAIC,MAAW,WAAW,MAAMA,EAAO,MAAM,oBAAoBF,CAAE,EAAE,CAAC,GAAGA,CAAE,CAAC;AAAA,EAC1F,CAAA;AACH;"}
1
+ {"version":3,"file":"functions.js","sources":["../../../../../../../lib/util/helpers/src/functions.ts"],"sourcesContent":["import type { AnyFunction } from \"./types\";\n\nexport function isFunction(value: unknown): value is AnyFunction {\n return typeof value === \"function\";\n}\n\n/**\n * A utility class that ensures asynchronous locks, allowing only one task to proceed at a time.\n */\nexport class AwaitLock {\n private acquired = false;\n private resolvers: (() => void)[] = [];\n\n acquireAsync(): Promise<void> {\n if (!this.acquired) {\n this.acquired = true;\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n this.resolvers.push(resolve);\n });\n }\n\n release(): void {\n if (!this.acquired) {\n throw new Error(\"Cannot release not acquired lock\");\n }\n\n if (this.resolvers.length) {\n this.resolvers.shift()?.();\n } else {\n this.acquired = false;\n }\n }\n}\n\n/**\n * A utility to add a timeout to a promise, rejecting the promise if the timeout is exceeded.\n */\nexport function promiseTimeout<T>(prom: PromiseLike<T>, ms: number): Promise<T> {\n return Promise.race<T>([\n prom,\n new Promise((_r, reject) => setTimeout(() => reject(Error(`Timeout exceeded ${ms}`)), ms)),\n ]);\n}\n\n/**\n * Debounce utility: delays the execution of a function until a certain time has passed since the last call.\n * @param callback\n * @param ms\n * @param immediate (if first call is required)\n * @returns\n */\nexport function debounce<F extends AnyFunction>(\n callback: F,\n ms: number,\n immediate?: boolean,\n): (...args: Parameters<F>) => void {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n return function (this: unknown, ...args: Parameters<F>) {\n const i = immediate && !timeout;\n if (i) {\n callback.apply(this, args);\n }\n if (timeout) {\n clearTimeout(timeout);\n }\n timeout = setTimeout(() => {\n timeout = undefined;\n if (!i) {\n callback.apply(this, args);\n }\n }, ms);\n };\n}\n\n/**\n * Throttle utility: ensures a function is called at most once every `ms` milliseconds.\n * @param callback\n * @param ms milliseconds\n * @param trailing (ensure last call)\n * @returns\n */\nexport function throttle<F extends AnyFunction>(\n callback: F,\n ms: number,\n trailing = true,\n): (...args: Parameters<F>) => void {\n let t = 0,\n call: AnyFunction | null;\n return function (this: unknown, ...args: Parameters<F>) {\n call = () => {\n callback.apply(this, args);\n t = new Date().getTime() + ms;\n call = null;\n if (trailing) {\n setTimeout(() => {\n call?.();\n }, ms);\n }\n };\n if (new Date().getTime() > t) call();\n };\n}\n\n/**\n * Memoization utility: caches results of function calls based on their arguments to avoid redundant calculations.\n */\nexport const memoize = <F extends AnyFunction>(fn: F) => {\n const cache = new Map();\n return function (...args: Parameters<F>): ReturnType<F> {\n const key = JSON.stringify(args);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return cache.has(key)\n ? cache.get(key)\n : cache.set(key, fn.call(null, ...args)) && cache.get(key);\n };\n};\n\n/**\n * Function wrapper utility: executes a function before the main function is called.\n */\nexport const wrapFunction = <T extends unknown[], U>(fn: (...args: T) => U, before: () => void) => {\n return (...args: T): U => {\n before();\n return fn(...args);\n };\n};\n\n/**\n * Function piping utility: allows chaining of functions by passing the result of one as input to another\n */\nexport function pipe<A, B>(cb: (a: A) => B) {\n const fn = (a: A) => cb(a);\n\n fn.pipe = <C>(next: (b: B) => C) => pipe((a: A) => next(cb(a)));\n\n return fn;\n}\n\n/**\n * Ensures that only one request can be processed at a time.\n */\nexport function exclusiveRequest<A, R>(request: (...args: A[]) => Promise<R>) {\n let counter = 0n;\n let ongoingOperation: Promise<R> | undefined;\n\n return async function (...params: A[]): Promise<\n | {\n ok: false;\n }\n | {\n ok: true;\n value: R;\n }\n > {\n const myId = ++counter;\n\n try {\n await ongoingOperation;\n } catch {\n // ignoring the error here, original caller will receive any rejections\n }\n\n // checking that this update is still the most recent\n if (counter !== myId) {\n return {\n ok: false,\n };\n }\n\n const promise = request(...params);\n\n ongoingOperation = promise;\n\n const value = await promise;\n\n return {\n ok: true,\n value,\n };\n };\n}\n\nexport function tryDo<R1>(fn: () => R1): R1 | undefined;\nexport function tryDo<R1, R2>(fn: () => R1, fallback: (cause: unknown) => R2): R1 | R2;\nexport function tryDo(fn: () => unknown, fallback?: (cause: unknown) => unknown) {\n try {\n return fn();\n } catch (cause: unknown) {\n return fallback?.(cause);\n }\n}\n"],"names":["promiseTimeout","prom","ms","_r","reject","debounce","callback","immediate","timeout","args"],"mappings":"AAwCM,SAAUA,EAAkBC,GAAsBC,GAAU;AAChE,SAAO,QAAQ,KAAQ;AAAA,IACrBD;AAAA,IACA,IAAI,QAAQ,CAACE,GAAIC,MAAW,WAAW,MAAMA,EAAO,MAAM,oBAAoBF,CAAE,EAAE,CAAC,GAAGA,CAAE,CAAC;AAAA,EAC1F,CAAA;AACH;AASgB,SAAAG,EACdC,GACAJ,GACAK,GAAmB;AAEnB,MAAIC;AACJ,SAAO,YAA4BC,GAAmB;AAKpD,IAAID,KACF,aAAaA,CAAO,GAEtBA,IAAU,WAAW,MAAK;AACxB,MAAAA,IAAU,QAERF,EAAS,MAAM,MAAMG,CAAI;AAAA,IAE7B,GAAGP,CAAE;AAAA,EACP;AACF;"}
@@ -1 +1 @@
1
- {"version":3,"file":"objects.js","sources":["../../../../../../../lib/util/helpers/src/objects.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { PartialBy, PlainObject } from \"./types\";\nimport { isNil } from \"./utils\";\n\n/**\n * Alias to Array.isArray\n */\nexport const isArray = Array.isArray;\n\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport function isNonPrimitive<V, T extends PlainObject<V> | V[]>(obj: T | unknown): obj is T {\n return obj !== null && typeof obj === \"object\";\n}\n\nexport function isObject(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Checks if the given value is a plain object.\n *\n * A plain object is defined as an object created by the `{}` literal,\n * an object created with `Object.create(null)`, or an object with a\n * prototype that resolves to `Object.prototype`.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a plain object, otherwise `false`.\n *\n * @example\n * ```typescript\n * isPlainObject({}); // true\n * isPlainObject(Object.create(null)); // true\n * isPlainObject(new Date()); // false\n * isPlainObject(null); // false\n * isPlainObject([]); // false\n * ```\n */\nexport function isPlainObject(value: unknown): value is PlainObject {\n if (!isObject(value)) {\n return false;\n }\n\n const prototype: unknown = Object.getPrototypeOf(value);\n\n return (\n prototype === null ||\n prototype === Object.prototype ||\n Object.getPrototypeOf(prototype) === null\n );\n}\n\nexport function map<U, T extends Record<string, unknown>>(\n obj: T,\n callback: (curr: T[keyof T], key: keyof T) => U,\n) {\n const keys = Object.keys(obj) as Array<keyof T>;\n\n return keys.map((key: keyof T) => {\n return callback(obj[key], key);\n });\n}\n\nfunction definedKeysSize(obj: PlainObject) {\n return Object.values(obj).reduce((length: number, v) => {\n return v !== undefined ? length + 1 : length;\n }, 0);\n}\n\n/**\n * Performs a deep equality check between two values, `a` and `b`, to determine if they are JSON-equivalent.\n *\n * JSON equivalence means that the two values are strictly equal in structure and content, including arrays and plain objects.\n * Non-primitive values that are neither arrays nor plain objects will throw an error.\n *\n * @param a - The first value to compare.\n * @param b - The second value to compare.\n * @returns `true` if the values are JSON-equivalent, otherwise `false`.\n *\n * @throws If the values are non-primitive and not arrays or plain objects.\n *\n * @example\n * ```typescript\n * isJsonEqual(1, 1); // true\n * isJsonEqual({ a: 1 }, { a: 1 }); // true\n * isJsonEqual([1, 2], [1, 2]); // true\n * isJsonEqual({ a: 1 }, { a: 2 }); // false\n * isJsonEqual([1, 2], [2, 1]); // false\n * isJsonEqual(new Date(), new Date()); // Error\n * ```\n */\nexport function isJsonEqual(a: unknown, b: unknown): boolean {\n if (!(isNonPrimitive(a) && isNonPrimitive(b))) {\n return a === b;\n }\n\n if (isArray(a) && isArray(b)) {\n if (a.length !== b.length) {\n return false;\n } else {\n return [...a.keys()].every((k) => isJsonEqual(a[k], b[k]));\n }\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n if (definedKeysSize(a) !== definedKeysSize(b)) {\n return false;\n }\n\n return Object.keys(a).every((k) => isJsonEqual(a[k], b[k]));\n }\n\n /* eslint-disable @typescript-eslint/no-base-to-string */\n throw Error(`Cannot compare a ${String(a)} and b ${String(b)}`);\n}\n\n/**\n * Alias to isJsonEqual function\n * @deprecated change to isJsonEqual\n */\nexport const deepEqual = isJsonEqual;\n\nexport function deepClone<T>(obj: T): T {\n if (Array.isArray(obj)) {\n const copy: any[] = [];\n for (let i = 0; i < obj.length; i++) {\n copy[i] = deepClone(obj[i]) as unknown;\n }\n return copy as T;\n } else if (isPlainObject(obj)) {\n const copy: Record<string, any> = {};\n Object.keys(obj).forEach((k) => {\n copy[k] = deepClone(obj[k]);\n });\n return copy as T;\n } else {\n return obj;\n }\n}\n\nexport function shallowClone<T>(obj: T): T {\n if (isNil(obj)) return obj;\n if (Array.isArray(obj)) return obj.slice() as T;\n if (isPlainObject(obj)) return Object.assign({}, obj) as T;\n if (obj instanceof Map) return new Map(obj) as T;\n if (obj instanceof Set) return new Set(obj) as T;\n throw Error(`Not implemented clone strategy for ${JSON.stringify(obj)}`);\n}\n\nexport function shallowDiff<T>(to: T, from: T): Partial<T> {\n const diff: Partial<T> = {};\n\n for (const key in from) {\n if (from[key] !== to[key]) {\n diff[key] = to[key];\n }\n }\n\n return diff;\n}\n\nexport function bindMethods<O extends Record<string, unknown>>(obj: O) {\n Object.entries(obj).forEach(([key, m]) => {\n if (m instanceof Function) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n obj[key as keyof O] = m.bind(obj);\n }\n });\n\n return obj;\n}\n\nexport function setProp<O, K extends keyof O>(obj: O, key: K, value: O[K]) {\n obj[key] = value;\n return obj;\n}\n\nexport function getProp<O, K extends keyof O>(obj: O, key: K): O[K] {\n return obj[key];\n}\n\nexport function shiftProp<O, K extends keyof O>(obj: O, key: K): [O[K], Omit<O, K>] {\n obj = { ...obj };\n const val = obj[key];\n delete obj[key];\n return [val, obj];\n}\n\nexport function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {\n return Object.assign({}, ...keys.map((k) => ({ [k]: obj[k] }))) as Pick<T, K>;\n}\n\nexport function pickValues<T, K extends keyof T>(obj: T, ...keys: K[]) {\n return keys.map((k) => obj[k]);\n}\n\nexport function omit<T, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K> {\n const o = Object.assign({}, obj) as PartialBy<T, K>;\n keys.forEach((k) => delete o[k]);\n return o;\n}\n\n/**\n * Performs a deep patch of the target object or array using the source object or array.\n *\n * This function recursively merges properties of the source into the target:\n * - If a property in both target and source is a plain object, they are recursively merged.\n * - If a property in both target and source is an array of the same length, the arrays are recursively patched element by element.\n * - Otherwise, the property value in the target is replaced by the corresponding value from the source.\n *\n * The patch is applied in-place to the target object or array, which is also returned for convenience.\n *\n * @typeParam T - The type of the target and source, which must be either a plain object or an array.\n * @param target - The target object or array to be patched. This object/array is modified in-place.\n * @param source - The source object or array providing the new values for the patch.\n * @returns The modified target object or array.\n *\n * @example\n * ```typescript\n * const target = { a: { b: 1 }, c: [1, 2] };\n * const source = { a: { b: 2 }, c: [3, 4], d: 5 };\n * const result = deepPatch(target, source);\n * // target is now: { a: { b: 2 }, c: [3, 4], d: 5 }\n * // result is the same reference as target.\n *\n * const targetArray = [{ a: 1 }, { b: 2 }];\n * const sourceArray = [{ a: 2 }, { b: 3 }];\n * const resultArray = deepPatch(targetArray, sourceArray);\n * // targetArray is now: [{ a: 2 }, { b: 3 }]\n * ```\n */\nexport function deepPatch<T extends PlainObject | unknown[]>(target: T, source: T) {\n const sk = new Set<keyof T>([\n ...(Object.keys(target) as (keyof T)[]),\n ...(Object.keys(source) as (keyof T)[]),\n ]);\n\n sk.forEach((key) => {\n const t = target[key];\n const s = source[key];\n if (isPlainObject(t) && isPlainObject(s)) {\n deepPatch(t, s);\n } else if (isArray(t) && isArray(s) && t.length === s.length) {\n deepPatch(t, s);\n } else {\n target[key] = s;\n }\n });\n\n return target;\n}\n"],"names":["isArray","isNonPrimitive","obj","isObject","value","isPlainObject","prototype","definedKeysSize","length","v","isJsonEqual","a","b","k","deepClone","copy","i"],"mappings":"AAQO,MAAMA,IAAU,MAAM;AAGvB,SAAUC,EAAkDC,GAAgB;AAChF,SAAOA,MAAQ,QAAQ,OAAOA,KAAQ;AACxC;AAEM,SAAUC,EAASC,GAAc;AACrC,SAAO,OAAOA,KAAU,YAAYA,MAAU;AAChD;AAqBM,SAAUC,EAAcD,GAAc;AAC1C,MAAI,CAACD,EAASC,CAAK;AACjB,WAAO;AAGT,QAAME,IAAqB,OAAO,eAAeF,CAAK;AAEtD,SACEE,MAAc,QACdA,MAAc,OAAO,aACrB,OAAO,eAAeA,CAAS,MAAM;AAEzC;AAaA,SAASC,EAAgBL,GAAgB;AACvC,SAAO,OAAO,OAAOA,CAAG,EAAE,OAAO,CAACM,GAAgBC,MACzCA,MAAM,SAAYD,IAAS,IAAIA,GACrC,CAAC;AACN;AAwBM,SAAUE,EAAYC,GAAYC,GAAU;AAChD,MAAI,EAAEX,EAAeU,CAAC,KAAKV,EAAeW,CAAC;AACzC,WAAOD,MAAMC;AAGf,MAAIZ,EAAQW,CAAC,KAAKX,EAAQY,CAAC;AACzB,WAAID,EAAE,WAAWC,EAAE,SACV,KAEA,CAAC,GAAGD,EAAE,KAAI,CAAE,EAAE,MAAM,CAACE,MAAMH,EAAYC,EAAEE,CAAC,GAAGD,EAAEC,CAAC,CAAC,CAAC;AAI7D,MAAIR,EAAcM,CAAC,KAAKN,EAAcO,CAAC;AACrC,WAAIL,EAAgBI,CAAC,MAAMJ,EAAgBK,CAAC,IACnC,KAGF,OAAO,KAAKD,CAAC,EAAE,MAAM,CAACE,MAAMH,EAAYC,EAAEE,CAAC,GAAGD,EAAEC,CAAC,CAAC,CAAC;AAI5D,QAAM,MAAM,oBAAoB,OAAOF,CAAC,CAAC,UAAU,OAAOC,CAAC,CAAC,EAAE;AAChE;AAQM,SAAUE,EAAaZ,GAAM;AACjC,MAAI,MAAM,QAAQA,CAAG,GAAG;AACtB,UAAMa,IAAc,CAAA;AACpB,aAASC,IAAI,GAAGA,IAAId,EAAI,QAAQc;AAC9B,MAAAD,EAAKC,CAAC,IAAIF,EAAUZ,EAAIc,CAAC,CAAC;AAE5B,WAAOD;AAAA,EACT,WAAWV,EAAcH,CAAG,GAAG;AAC7B,UAAMa,IAA4B,CAAA;AAClC,kBAAO,KAAKb,CAAG,EAAE,QAAQ,CAACW,MAAK;AAC7B,MAAAE,EAAKF,CAAC,IAAIC,EAAUZ,EAAIW,CAAC,CAAC;AAAA,IAC5B,CAAC,GACME;AAAA,EACT;AACE,WAAOb;AAEX;"}
1
+ {"version":3,"file":"objects.js","sources":["../../../../../../../lib/util/helpers/src/objects.ts"],"sourcesContent":["/**/\n\nimport type { PartialBy, PlainObject } from \"./types\";\nimport { isNil } from \"./utils\";\n\n/**\n * Alias to Array.isArray\n */\nexport const isArray = Array.isArray;\n\n//\nexport function isNonPrimitive<V, T extends PlainObject<V> | V[]>(obj: T | unknown): obj is T {\n return obj !== null && typeof obj === \"object\";\n}\n\nexport function isObject(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Checks if the given value is a plain object.\n *\n * A plain object is defined as an object created by the `{}` literal,\n * an object created with `Object.create(null)`, or an object with a\n * prototype that resolves to `Object.prototype`.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a plain object, otherwise `false`.\n *\n * @example\n * ```typescript\n * isPlainObject({}); // true\n * isPlainObject(Object.create(null)); // true\n * isPlainObject(new Date()); // false\n * isPlainObject(null); // false\n * isPlainObject([]); // false\n * ```\n */\nexport function isPlainObject(value: unknown): value is PlainObject {\n if (!isObject(value)) {\n return false;\n }\n\n const prototype: unknown = Object.getPrototypeOf(value);\n\n return (\n prototype === null ||\n prototype === Object.prototype ||\n Object.getPrototypeOf(prototype) === null\n );\n}\n\nexport function map<U, T extends Record<string, unknown>>(\n obj: T,\n callback: (curr: T[keyof T], key: keyof T) => U,\n) {\n const keys = Object.keys(obj) as Array<keyof T>;\n\n return keys.map((key: keyof T) => {\n return callback(obj[key], key);\n });\n}\n\nfunction definedKeysSize(obj: PlainObject) {\n return Object.values(obj).reduce((length: number, v) => {\n return v !== undefined ? length + 1 : length;\n }, 0);\n}\n\n/**\n * Performs a deep equality check between two values, `a` and `b`, to determine if they are JSON-equivalent.\n *\n * JSON equivalence means that the two values are strictly equal in structure and content, including arrays and plain objects.\n * Non-primitive values that are neither arrays nor plain objects will throw an error.\n *\n * @param a - The first value to compare.\n * @param b - The second value to compare.\n * @returns `true` if the values are JSON-equivalent, otherwise `false`.\n *\n * @throws If the values are non-primitive and not arrays or plain objects.\n *\n * @example\n * ```typescript\n * isJsonEqual(1, 1); // true\n * isJsonEqual({ a: 1 }, { a: 1 }); // true\n * isJsonEqual([1, 2], [1, 2]); // true\n * isJsonEqual({ a: 1 }, { a: 2 }); // false\n * isJsonEqual([1, 2], [2, 1]); // false\n * isJsonEqual(new Date(), new Date()); // Error\n * ```\n */\nexport function isJsonEqual(a: unknown, b: unknown): boolean {\n if (!(isNonPrimitive(a) && isNonPrimitive(b))) {\n return a === b;\n }\n\n if (isArray(a) && isArray(b)) {\n if (a.length !== b.length) {\n return false;\n } else {\n return [...a.keys()].every((k) => isJsonEqual(a[k], b[k]));\n }\n }\n\n if (isPlainObject(a) && isPlainObject(b)) {\n if (definedKeysSize(a) !== definedKeysSize(b)) {\n return false;\n }\n\n return Object.keys(a).every((k) => isJsonEqual(a[k], b[k]));\n }\n\n throw Error(`Cannot compare a ${String(a)} and b ${String(b)}`);\n}\n\n/**\n * Alias to isJsonEqual function\n * @deprecated change to isJsonEqual\n */\nexport const deepEqual = isJsonEqual;\n\nexport function deepClone<T>(obj: T): T {\n if (Array.isArray(obj)) {\n const copy: any[] = [];\n for (let i = 0; i < obj.length; i++) {\n copy[i] = deepClone(obj[i]) as unknown;\n }\n return copy as T;\n } else if (isPlainObject(obj)) {\n const copy: Record<string, any> = {};\n Object.keys(obj).forEach((k) => {\n copy[k] = deepClone(obj[k]);\n });\n return copy as T;\n } else {\n return obj;\n }\n}\n\nexport function shallowClone<T>(obj: T): T {\n if (isNil(obj)) return obj;\n if (Array.isArray(obj)) return obj.slice() as T;\n if (isPlainObject(obj)) return Object.assign({}, obj) as T;\n if (obj instanceof Map) return new Map(obj) as T;\n if (obj instanceof Set) return new Set(obj) as T;\n throw Error(`Not implemented clone strategy for ${JSON.stringify(obj)}`);\n}\n\nexport function shallowDiff<T>(to: T, from: T): Partial<T> {\n const diff: Partial<T> = {};\n\n for (const key in from) {\n if (from[key] !== to[key]) {\n diff[key] = to[key];\n }\n }\n\n return diff;\n}\n\nexport function bindMethods<O extends Record<string, unknown>>(obj: O) {\n Object.entries(obj).forEach(([key, m]) => {\n if (m instanceof Function) {\n //\n obj[key as keyof O] = m.bind(obj);\n }\n });\n\n return obj;\n}\n\nexport function setProp<O, K extends keyof O>(obj: O, key: K, value: O[K]) {\n obj[key] = value;\n return obj;\n}\n\nexport function getProp<O, K extends keyof O>(obj: O, key: K): O[K] {\n return obj[key];\n}\n\nexport function shiftProp<O, K extends keyof O>(obj: O, key: K): [O[K], Omit<O, K>] {\n obj = { ...obj };\n const val = obj[key];\n delete obj[key];\n return [val, obj];\n}\n\nexport function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {\n return Object.assign({}, ...keys.map((k) => ({ [k]: obj[k] }))) as Pick<T, K>;\n}\n\nexport function pickValues<T, K extends keyof T>(obj: T, ...keys: K[]) {\n return keys.map((k) => obj[k]);\n}\n\nexport function omit<T, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K> {\n const o = Object.assign({}, obj) as PartialBy<T, K>;\n keys.forEach((k) => delete o[k]);\n return o;\n}\n\n/**\n * Performs a deep patch of the target object or array using the source object or array.\n *\n * This function recursively merges properties of the source into the target:\n * - If a property in both target and source is a plain object, they are recursively merged.\n * - If a property in both target and source is an array of the same length, the arrays are recursively patched element by element.\n * - Otherwise, the property value in the target is replaced by the corresponding value from the source.\n *\n * The patch is applied in-place to the target object or array, which is also returned for convenience.\n *\n * @typeParam T - The type of the target and source, which must be either a plain object or an array.\n * @param target - The target object or array to be patched. This object/array is modified in-place.\n * @param source - The source object or array providing the new values for the patch.\n * @returns The modified target object or array.\n *\n * @example\n * ```typescript\n * const target = { a: { b: 1 }, c: [1, 2] };\n * const source = { a: { b: 2 }, c: [3, 4], d: 5 };\n * const result = deepPatch(target, source);\n * // target is now: { a: { b: 2 }, c: [3, 4], d: 5 }\n * // result is the same reference as target.\n *\n * const targetArray = [{ a: 1 }, { b: 2 }];\n * const sourceArray = [{ a: 2 }, { b: 3 }];\n * const resultArray = deepPatch(targetArray, sourceArray);\n * // targetArray is now: [{ a: 2 }, { b: 3 }]\n * ```\n */\nexport function deepPatch<T extends PlainObject | unknown[]>(target: T, source: T) {\n const sk = new Set<keyof T>([\n ...(Object.keys(target) as (keyof T)[]),\n ...(Object.keys(source) as (keyof T)[]),\n ]);\n\n sk.forEach((key) => {\n const t = target[key];\n const s = source[key];\n if (isPlainObject(t) && isPlainObject(s)) {\n deepPatch(t, s);\n } else if (isArray(t) && isArray(s) && t.length === s.length) {\n deepPatch(t, s);\n } else {\n target[key] = s;\n }\n });\n\n return target;\n}\n"],"names":["isArray","isNonPrimitive","obj","isObject","value","isPlainObject","prototype","definedKeysSize","length","v","isJsonEqual","a","b","k","deepClone","copy","i"],"mappings":"AAQO,MAAMA,IAAU,MAAM;AAGvB,SAAUC,EAAkDC,GAAgB;AAChF,SAAOA,MAAQ,QAAQ,OAAOA,KAAQ;AACxC;AAEM,SAAUC,EAASC,GAAc;AACrC,SAAO,OAAOA,KAAU,YAAYA,MAAU;AAChD;AAqBM,SAAUC,EAAcD,GAAc;AAC1C,MAAI,CAACD,EAASC,CAAK;AACjB,WAAO;AAGT,QAAME,IAAqB,OAAO,eAAeF,CAAK;AAEtD,SACEE,MAAc,QACdA,MAAc,OAAO,aACrB,OAAO,eAAeA,CAAS,MAAM;AAEzC;AAaA,SAASC,EAAgBL,GAAgB;AACvC,SAAO,OAAO,OAAOA,CAAG,EAAE,OAAO,CAACM,GAAgBC,MACzCA,MAAM,SAAYD,IAAS,IAAIA,GACrC,CAAC;AACN;AAwBM,SAAUE,EAAYC,GAAYC,GAAU;AAChD,MAAI,EAAEX,EAAeU,CAAC,KAAKV,EAAeW,CAAC;AACzC,WAAOD,MAAMC;AAGf,MAAIZ,EAAQW,CAAC,KAAKX,EAAQY,CAAC;AACzB,WAAID,EAAE,WAAWC,EAAE,SACV,KAEA,CAAC,GAAGD,EAAE,KAAI,CAAE,EAAE,MAAM,CAACE,MAAMH,EAAYC,EAAEE,CAAC,GAAGD,EAAEC,CAAC,CAAC,CAAC;AAI7D,MAAIR,EAAcM,CAAC,KAAKN,EAAcO,CAAC;AACrC,WAAIL,EAAgBI,CAAC,MAAMJ,EAAgBK,CAAC,IACnC,KAGF,OAAO,KAAKD,CAAC,EAAE,MAAM,CAACE,MAAMH,EAAYC,EAAEE,CAAC,GAAGD,EAAEC,CAAC,CAAC,CAAC;AAG5D,QAAM,MAAM,oBAAoB,OAAOF,CAAC,CAAC,UAAU,OAAOC,CAAC,CAAC,EAAE;AAChE;AAQM,SAAUE,EAAaZ,GAAM;AACjC,MAAI,MAAM,QAAQA,CAAG,GAAG;AACtB,UAAMa,IAAc,CAAA;AACpB,aAASC,IAAI,GAAGA,IAAId,EAAI,QAAQc;AAC9B,MAAAD,EAAKC,CAAC,IAAIF,EAAUZ,EAAIc,CAAC,CAAC;AAE5B,WAAOD;AAAA,EACT,WAAWV,EAAcH,CAAG,GAAG;AAC7B,UAAMa,IAA4B,CAAA;AAClC,kBAAO,KAAKb,CAAG,EAAE,QAAQ,CAACW,MAAK;AAC7B,MAAAE,EAAKF,CAAC,IAAIC,EAAUZ,EAAIW,CAAC,CAAC;AAAA,IAC5B,CAAC,GACME;AAAA,EACT;AACE,WAAOb;AAEX;"}
package/dist/lib.d.ts CHANGED
@@ -19,6 +19,7 @@ export * from './components/PlAnnotations';
19
19
  export * from './components/PlBtnExportArchive';
20
20
  export * from './components/PlAdvancedFilter';
21
21
  export * from './defineApp';
22
+ export { usePluginData } from './usePluginData';
22
23
  export * from './createModel';
23
24
  export * from './types';
24
25
  export * from './defineStore';
package/dist/lib.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAClG,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAEhG,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,cAAc,aAAa,CAAC;AAE5B,cAAc,+BAA+B,CAAC;AAE9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sCAAsC,CAAC;AAErD,cAAc,4BAA4B,CAAC;AAE3C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,oCAAoC,CAAC;AAEnD,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAE9C,cAAc,aAAa,CAAC;AAE5B,cAAc,eAAe,CAAC;AAE9B,cAAc,SAAS,CAAC;AAExB,cAAc,eAAe,CAAC;AAE9B,cAAc,UAAU,CAAC;AAEzB,cAAc,SAAS,CAAC;AAExB,cAAc,cAAc,CAAC;AAE7B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,uBAAuB,CAAC"}
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAClG,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAEhG,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,cAAc,aAAa,CAAC;AAE5B,cAAc,+BAA+B,CAAC;AAE9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sCAAsC,CAAC;AAErD,cAAc,4BAA4B,CAAC;AAE3C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,oCAAoC,CAAC;AAEnD,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAE9C,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,cAAc,eAAe,CAAC;AAE9B,cAAc,SAAS,CAAC;AAExB,cAAc,eAAe,CAAC;AAE9B,cAAc,UAAU,CAAC;AAEzB,cAAc,SAAS,CAAC;AAExB,cAAc,cAAc,CAAC;AAE7B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,uBAAuB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -48,7 +48,7 @@ export type AppSettings = {
48
48
  */
49
49
  debug?: boolean;
50
50
  /**
51
- * Debounce span in ms (default is 100ms)
51
+ * Debounce span in ms (default is 200ms)
52
52
  */
53
53
  debounceSpan?: number;
54
54
  /**
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Composable for accessing and updating plugin-specific data.
3
+ *
4
+ * Plugin components are self-contained: they use this composable to read/write
5
+ * their own data slice from BlockStorage without knowing about the parent block's data.
6
+ *
7
+ * Requires a V3 block (BlockModelV3). Throws if used in a V1/V2 block.
8
+ *
9
+ * @param pluginId - The plugin instance ID (must match the ID used in BlockModelV3.plugin()).
10
+ * Must be a static value; changing it after mount will not re-bind the composable.
11
+ * @returns `{ data, updateData }` where `data` is a reactive ref to the plugin's data,
12
+ * and `updateData` returns a promise resolving to `true` if the mutation was sent,
13
+ * or `false` if data is not yet available.
14
+ *
15
+ * @example
16
+ * ```vue
17
+ * <script setup lang="ts">
18
+ * const { data, updateData } = usePluginData<CounterData>('counter');
19
+ *
20
+ * function increment() {
21
+ * updateData((d) => ({ ...d, count: d.count + 1 }));
22
+ * }
23
+ * </script>
24
+ * ```
25
+ */
26
+ export declare function usePluginData<Data>(pluginId: string): {
27
+ data: import('vue').ComputedRef<Data | undefined>;
28
+ updateData: (cb: (current: Data) => Data) => Promise<boolean>;
29
+ };
30
+ //# sourceMappingURL=usePluginData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePluginData.d.ts","sourceRoot":"","sources":["../src/usePluginData.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM;;qBAwB1B,CAAC,OAAO,EAAE,IAAI,KAAK,IAAI,KAAG,OAAO,CAAC,OAAO,CAAC;EAQnE"}
@@ -0,0 +1,22 @@
1
+ import { inject as i, computed as u } from "vue";
2
+ import { deepClone as s } from "./lib/util/helpers/dist/objects.js";
3
+ import { pluginDataKey as l } from "./defineApp.js";
4
+ function d(t) {
5
+ const e = i(l);
6
+ if (!e)
7
+ throw new Error(
8
+ "usePluginData requires a V3 block (BlockModelV3). Make sure the block uses apiVersion 3 and the plugin is installed."
9
+ );
10
+ e.initPluginDataSlot(t);
11
+ const a = u(() => e.pluginDataMap[t]);
12
+ return { data: a, updateData: (o) => {
13
+ const r = a.value;
14
+ if (r === void 0) return Promise.resolve(!1);
15
+ const n = o(s(r));
16
+ return e.setPluginData(t, n);
17
+ } };
18
+ }
19
+ export {
20
+ d as usePluginData
21
+ };
22
+ //# sourceMappingURL=usePluginData.js.map