@razaman2/reactive-view 0.0.34 → 0.1.0-beta.10

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.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
9
  var __getProtoOf = Object.getPrototypeOf;
@@ -19,6 +21,7 @@ var __spreadValues = (a, b) => {
19
21
  }
20
22
  return a;
21
23
  };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
25
  var __objRest = (source, exclude) => {
23
26
  var target = {};
24
27
  for (var prop in source)
@@ -32,8 +35,8 @@ var __objRest = (source, exclude) => {
32
35
  return target;
33
36
  };
34
37
  var __export = (target, all) => {
35
- for (var name2 in all)
36
- __defProp(target, name2, { get: all[name2], enumerable: true });
38
+ for (var name in all)
39
+ __defProp(target, name, { get: all[name], enumerable: true });
37
40
  };
38
41
  var __copyProps = (to, from, except, desc) => {
39
42
  if (from && typeof from === "object" || typeof from === "function") {
@@ -57,18 +60,25 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
57
60
  var index_exports = {};
58
61
  __export(index_exports, {
59
62
  MergeStyles: () => MergeStyles,
63
+ Prop: () => Prop,
60
64
  StyleParser: () => StyleParser,
61
65
  access: () => access,
66
+ dataPath: () => dataPath,
62
67
  default: () => index_default,
68
+ defineReactiveView: () => defineReactiveView,
63
69
  extendVnode: () => extendVnode,
70
+ getData: () => getData,
64
71
  getDate: () => getDate,
65
72
  getProps: () => getProps,
66
73
  getReactiveViewComponent: () => getReactiveViewComponent,
67
74
  safeRequest: () => safeRequest,
75
+ setData: () => setData,
68
76
  setup: () => setup,
77
+ showComponent: () => showComponent,
69
78
  useSubscription: () => useSubscription
70
79
  });
71
80
  module.exports = __toCommonJS(index_exports);
81
+ var import_object_manager2 = __toESM(require("@razaman2/object-manager"));
72
82
 
73
83
  // src/Subscription.ts
74
84
  var Subscription = class _Subscription {
@@ -79,34 +89,34 @@ var Subscription = class _Subscription {
79
89
  static create() {
80
90
  return new _Subscription();
81
91
  }
82
- subscribe(name2, handler, data) {
83
- if (this.isNameAvailable(name2)) {
92
+ subscribe(name, handler, data) {
93
+ if (this.isNameAvailable(name)) {
84
94
  this.subscriptions.push({
85
- name: name2,
95
+ name,
86
96
  handler
87
97
  });
88
- this.data[name2] = data;
98
+ this.data[name] = data;
89
99
  }
90
100
  return this;
91
101
  }
92
- replace(name2, handler, data) {
93
- this.unsubscribe(name2);
94
- return this.subscribe(name2, handler, data);
102
+ replace(name, handler, data) {
103
+ this.unsubscribe(name);
104
+ return this.subscribe(name, handler, data);
95
105
  }
96
106
  unsubscribe(param1) {
97
107
  if (!Array.isArray(param1)) {
98
108
  param1 = param1 ? [param1] : [];
99
109
  }
100
- const log = (name2) => {
101
- return console.log(`%cUnsubscribed From Subscription (${name2})`, "background-color: yellow; color: green; font-weight: bold; padding: 3px;");
110
+ const log = (name) => {
111
+ return console.log(`%cUnsubscribed From Subscription (${name})`, "background-color: yellow; color: green; font-weight: bold; padding: 3px;");
102
112
  };
103
113
  if (param1.length) {
104
- param1.forEach((name2) => {
105
- const subscription = this.find(name2);
114
+ param1.forEach((name) => {
115
+ const subscription = this.find(name);
106
116
  if (subscription) {
107
117
  subscription.handler();
108
118
  this.remove(subscription);
109
- log(name2);
119
+ log(name);
110
120
  }
111
121
  });
112
122
  } else {
@@ -121,20 +131,20 @@ var Subscription = class _Subscription {
121
131
  size() {
122
132
  return this.subscriptions.length;
123
133
  }
124
- hasSubscription(name2) {
125
- return Boolean(this.find(name2));
134
+ hasSubscription(name) {
135
+ return Boolean(this.find(name));
126
136
  }
127
137
  remove(subscription) {
128
138
  this.subscriptions.splice(this.subscriptions.indexOf(subscription), 1);
129
139
  }
130
- find(name2) {
140
+ find(name) {
131
141
  return this.subscriptions.find((subscription) => {
132
- return subscription.name === name2;
142
+ return subscription.name === name;
133
143
  });
134
144
  }
135
- isNameAvailable(name2) {
136
- if (this.hasSubscription(name2)) {
137
- throw new Error(`There is already a subscription called "${name2}".`);
145
+ isNameAvailable(name) {
146
+ if (this.hasSubscription(name)) {
147
+ throw new Error(`There is already a subscription called "${name}".`);
138
148
  } else {
139
149
  return true;
140
150
  }
@@ -142,12 +152,12 @@ var Subscription = class _Subscription {
142
152
  registrations() {
143
153
  return this.subscriptions;
144
154
  }
145
- get(name2) {
146
- const subscription = this.find(name2);
155
+ get(name) {
156
+ const subscription = this.find(name);
147
157
  if (subscription) {
148
158
  return subscription;
149
159
  } else {
150
- throw new Error(`Subscription "${name2}" doesn't exist!`);
160
+ throw new Error(`Subscription "${name}" doesn't exist!`);
151
161
  }
152
162
  }
153
163
  };
@@ -167,8 +177,55 @@ var import_data_manager = __toESM(require("@razaman2/data-manager"));
167
177
  var import_vue = require("vue");
168
178
 
169
179
  // package.json
170
- var name = "@razaman2/reactive-view";
171
- var version = "0.0.34";
180
+ var version = "0.1.0-beta.10";
181
+ var package_default = {
182
+ name: "@razaman2/reactive-view",
183
+ version,
184
+ description: "This library enables you to build vue apps in an object oriented way. It provides a convenient approach to extend and override ui components. It provides a built in eventing system along with component data management.",
185
+ main: "dist/index.js",
186
+ module: "dist/index.mjs",
187
+ types: "dist/index.d.ts",
188
+ scripts: {
189
+ prepublishOnly: "npm run build",
190
+ build: "tsup src/index.ts --format cjs,esm --dts",
191
+ lint: "tsc",
192
+ test: "cd tests/vue-ts && npm run dev",
193
+ pr: "sh pr.sh"
194
+ },
195
+ keywords: [
196
+ "vue",
197
+ "vue-helper",
198
+ "reactive-view",
199
+ "vue-class-component",
200
+ "reactive-ui"
201
+ ],
202
+ author: "razaman2",
203
+ license: "MIT",
204
+ dependencies: {
205
+ "@razaman2/data-manager": "^3.3.8",
206
+ "@razaman2/event-emitter": "^2.1.1",
207
+ "@razaman2/object-manager": "^3.4.7",
208
+ "date-fns": "^4.1.0",
209
+ "date-fns-tz": "^3.2.0",
210
+ "tailwind-merge": "^3.5.0",
211
+ uuid: "^13.0.0"
212
+ },
213
+ peerDependencies: {
214
+ vue: ">=3.0.0"
215
+ },
216
+ devDependencies: {
217
+ "@types/uuid": "^11.0.0",
218
+ tsup: "^8.5.1",
219
+ typescript: "^5.9.3",
220
+ vitest: "^4.1.2"
221
+ },
222
+ publishConfig: {
223
+ access: "public"
224
+ },
225
+ files: [
226
+ "dist"
227
+ ]
228
+ };
172
229
 
173
230
  // src/ReactiveView.ts
174
231
  var setup = {
@@ -179,17 +236,16 @@ var setup = {
179
236
  var ReactiveView_default = {
180
237
  props: {
181
238
  setup: {},
239
+ beta: [Boolean, String],
182
240
  ReactiveView: {
183
241
  type: Boolean,
184
242
  default: true
185
243
  },
186
- instance: {
187
- default: (0, import_vue.ref)()
188
- },
244
+ instance: { default: (0, import_vue.ref)() },
189
245
  notifications: Object,
190
246
  subscriptions: Object,
191
247
  beforeSetData: Function,
192
- data: {},
248
+ data: { default: (0, import_vue.reactive)({}) },
193
249
  defaultData: {},
194
250
  getDefaultData: {
195
251
  type: Function,
@@ -209,142 +265,387 @@ var ReactiveView_default = {
209
265
  debug: {
210
266
  type: Boolean,
211
267
  default: false
212
- }
268
+ },
269
+ state: { default: (0, import_vue.reactive)({}) }
213
270
  },
214
271
  setup(props, context) {
215
- var _a, _b, _c, _d, _e, _f, _g;
216
- const template = (component2, vue2) => {
217
- return (0, import_vue.createVNode)(
218
- "div",
219
- context.slots.default ? context.attrs : __spreadValues({
220
- style: { color: "red", textAlign: "center" }
221
- }, context.attrs),
222
- context.slots.default ? context.slots.default({ component: component2, vue: vue2, props, context }) : `${props.modelName}: ${name}@${version}`
223
- );
272
+ var _a, _b, _c;
273
+ const subscriptions = [];
274
+ (0, import_vue.onBeforeUnmount)(() => subscriptions.forEach((subscription) => subscription()));
275
+ const diff = (before, after) => {
276
+ const changed = (0, import_vue.ref)(false);
277
+ const paths = Array.from(new Set(before.paths().concat(after.paths())));
278
+ const changes = paths.reduce((changes2, path) => {
279
+ if (before.get(path) !== after.get(path)) {
280
+ changes2.set(path, after.get(path));
281
+ changed.value = true;
282
+ }
283
+ return changes2;
284
+ }, import_object_manager.default.on({}));
285
+ return { before: before.get(), after: after.get(), changes: changes.get(), changed: changed.value };
286
+ };
287
+ const dataPath2 = (path) => {
288
+ try {
289
+ return context.attrs["data:path"](path);
290
+ } catch (e) {
291
+ return path;
292
+ }
293
+ };
294
+ const template = (component, vue2) => {
295
+ return (0, import_vue.createVNode)("div", context.slots.default ? context.attrs : __spreadValues({
296
+ style: { color: "red", textAlign: "center" }
297
+ }, context.attrs), context.slots.default ? context.slots.default({ component, vue: vue2, props, context }) : `${props.modelName}: ${package_default.name}@${package_default.version}`);
224
298
  };
225
299
  const isValid = (0, import_vue.ref)(false);
226
300
  const isReady = (0, import_vue.ref)(false);
227
- const isFunctionData = ["Function"].includes(((_a = props.data) != null ? _a : {}).constructor.name);
228
- const isAsyncFunctionData = ["AsyncFunction"].includes(((_b = props.data) != null ? _b : {}).constructor.name);
229
- const isPromiseData = ["Promise"].includes(((_c = props.data) != null ? _c : {}).constructor.name) || isAsyncFunctionData;
230
301
  const defer = (0, import_vue.ref)(typeof props.defer === "function" ? props.defer() : props.defer);
302
+ const isFunctionData = ["Function"].includes((_a = props.data) == null ? void 0 : _a.constructor.name);
303
+ const isAsyncFunctionData = ["AsyncFunction"].includes((_b = props.data) == null ? void 0 : _b.constructor.name);
304
+ const isAsyncData = ["Promise"].includes((_c = props.data) == null ? void 0 : _c.constructor.name) || isAsyncFunctionData;
231
305
  const vue = (0, import_vue.getCurrentInstance)();
232
- if (props.debug) {
233
- console.log("[ReactiveView]:", { props, context, vue, defer, data: props.data, isValid, isReady, isFunctionData, isAsyncFunctionData, isPromiseData });
234
- }
235
- if ((isPromiseData || isFunctionData) && !("defaultData" in vue.vnode.props)) {
236
- console.error("[ReactiveView]: defaultData is required for function or async data.");
237
- }
238
306
  const defaultData = props.getDefaultData(
239
- ((_d = vue.vnode.props) == null ? void 0 : _d.hasOwnProperty("defaultData")) ? vue.vnode.props.defaultData : ((_e = vue.vnode.props) == null ? void 0 : _e.hasOwnProperty("data")) ? Array.isArray(vue.vnode.props.data) ? [] : {} : {}
307
+ "defaultData" in vue.vnode.props ? vue.vnode.props.defaultData : "data" in vue.vnode.props ? Array.isArray((0, import_vue.unref)(vue.vnode.props.data)) ? [] : {} : {}
240
308
  );
241
309
  const datatype = Array.isArray(defaultData) ? [] : {};
242
- const config = {
243
- data: (0, import_vue.reactive)(import_object_manager.default.on(
244
- isPromiseData || isFunctionData || (0, import_vue.isRef)(props.data) || (0, import_vue.isReactive)(props.data) ? datatype : ((_f = vue.vnode.props) == null ? void 0 : _f.hasOwnProperty("data")) ? props.data : datatype
245
- ).clone()),
246
- defaultData: import_object_manager.default.on(defaultData).clone(),
247
- notifications: props.notifications,
248
- subscriptions: props.subscriptions,
249
- logging: props.logging,
250
- name: props.modelName
251
- };
252
- const model = new Proxy(props.model ? typeof props.model === "function" ? props.model(config) : props.model : new import_data_manager.default(config), {
253
- get(target, key, receiver) {
254
- if (key === "setData" || key === "replaceData") {
255
- return (...params) => {
256
- var _a2;
257
- const beforeSetData = (_a2 = access(component).beforeSetData) != null ? _a2 : props.beforeSetData;
258
- if (typeof beforeSetData === "function") {
259
- const after = import_object_manager.default.on(datatype).set(...params.length ? params : [defaultData]).get();
260
- const before = target.getData();
261
- beforeSetData({ before, after }, target);
310
+ const beta = () => {
311
+ var _a2;
312
+ const emit = (after, before) => {
313
+ if (vue && vue.vnode.el) {
314
+ const event = new CustomEvent("data:emit", {
315
+ bubbles: true,
316
+ // Key: allows it to travel up
317
+ composed: true,
318
+ // Key: allows it to cross Shadow DOM boundaries
319
+ detail: { before, after }
320
+ // Payload goes here
321
+ });
322
+ access(component).model.setData(after);
323
+ vue.vnode.el.dispatchEvent(event);
324
+ }
325
+ };
326
+ const proxy = (data) => {
327
+ return new Proxy(data, {
328
+ get(target, key, receiver) {
329
+ if (["setData", "replaceData"].includes(key.toString())) {
330
+ return (...params) => {
331
+ var _a3;
332
+ const beforeSetData = (_a3 = access(component).beforeSetData) != null ? _a3 : props.beforeSetData;
333
+ if (typeof beforeSetData === "function") {
334
+ const before = import_object_manager.default.on(target.getData());
335
+ const after = params.length ? import_object_manager.default.on(datatype).set(...params) : import_object_manager.default.on(datatype).set(defaultData);
336
+ const diff2 = access(component).diff(before, after);
337
+ if (beforeSetData(diff2, target)) {
338
+ target[key](...params);
339
+ }
340
+ } else {
341
+ target[key](...params);
342
+ }
343
+ return target;
344
+ };
262
345
  } else {
263
- target[key](...params);
346
+ return Reflect.get(target, key, receiver);
264
347
  }
265
- return target;
266
- };
348
+ }
349
+ });
350
+ };
351
+ const normalize = (data) => {
352
+ if ((0, import_vue.isRef)(data) || (0, import_vue.isReactive)(data)) {
353
+ return data;
354
+ } else if (isFunctionData || isAsyncData) {
355
+ return (0, import_vue.ref)(datatype);
267
356
  } else {
268
- return Reflect.get(target, key, receiver);
357
+ const props2 = "data" in vue.vnode.props;
358
+ try {
359
+ if (["Array", "Object"].includes(data.constructor.name)) {
360
+ return (0, import_vue.ref)(data);
361
+ } else {
362
+ return (0, import_vue.ref)(props2 ? { "": data } : datatype);
363
+ }
364
+ } catch (e) {
365
+ return (0, import_vue.ref)(props2 ? { "": data } : datatype);
366
+ }
269
367
  }
270
- }
271
- });
272
- const watchDataProp = (dataProp) => {
273
- var _a2, _b2, _c2;
274
- const config2 = typeof context.attrs["onUpdate:data"] === "function" ? { callback: context.attrs["onUpdate:data"] } : {
275
- callback: (_b2 = ((_a2 = context.attrs["onUpdate:data"]) != null ? _a2 : {}).callback) != null ? _b2 : context.attrs["data:callback"],
276
- options: Object.assign({
277
- immediate: context.attrs["data:immediate"],
278
- deep: context.attrs["data:deep"],
279
- once: context.attrs["data:once"]
280
- }, ((_c2 = context.attrs["onUpdate:data"]) != null ? _c2 : {}).options)
281
368
  };
282
- if (context.attrs["data:log"]) {
283
- console.log(`[ReactiveView]:data`, { config: config2, dataProp });
369
+ const config = {
370
+ data: normalize((_a2 = vue.vnode.props) == null ? void 0 : _a2.data),
371
+ defaultData: import_object_manager.default.on(defaultData).clone(),
372
+ notifications: props.notifications,
373
+ subscriptions: props.subscriptions,
374
+ name: props.modelName,
375
+ logging: props.logging
376
+ };
377
+ const model = props.model ? typeof props.model === "function" ? props.model(config) : props.model : import_data_manager.default.setConfig({ beforeGetData: (data) => (0, import_vue.isRef)(data) ? (0, import_vue.unref)(data) : data }, config);
378
+ const component = (0, import_vue.ref)({ parent: { self: vue.proxy }, self: { template, diff, emit, dataPath: dataPath2, model: proxy(model), isValid } });
379
+ if (context.attrs["onUpdate:model"] || context.attrs["update:model"]) {
380
+ const config2 = {
381
+ callback: typeof context.attrs["onUpdate:model"] === "function" ? context.attrs["onUpdate:model"] : context.attrs["update:model"],
382
+ options: {
383
+ immediate: context.attrs["model:immediate"],
384
+ deep: context.attrs["model:deep"],
385
+ once: context.attrs["model:once"]
386
+ }
387
+ };
388
+ const source = () => import_object_manager.default.on(model.getData()).clone();
389
+ subscriptions.push((0, import_vue.watch)(source, (after, before) => {
390
+ const diff2 = access(component).diff(import_object_manager.default.on(before), import_object_manager.default.on(after));
391
+ if (props.debug) {
392
+ console.warn(`[${props.modelName}]:model`, { diff: diff2, before, after });
393
+ }
394
+ if (diff2.changed) {
395
+ config2.callback(diff2, { component });
396
+ }
397
+ }, config2.options));
284
398
  }
285
- (0, import_vue.watch)(isFunctionData || (0, import_vue.isRef)(dataProp) || (0, import_vue.isReactive)(dataProp) ? dataProp : () => dataProp, (after, before) => {
399
+ const track = (source, options = {}) => {
400
+ var _a3, _b2, _c2, _d, _e;
401
+ subscriptions.push((0, import_vue.watch)(source, async (after, before) => {
402
+ const diff2 = access(component).diff(import_object_manager.default.on(before), import_object_manager.default.on(after));
403
+ const callback = context.attrs["data:callback"];
404
+ if (props.debug) {
405
+ console.warn(`[${props.modelName}]:data`, { diff: diff2, callback, before, after, props, context, component });
406
+ }
407
+ if (typeof callback === "function") {
408
+ callback(diff2, { component });
409
+ } else {
410
+ model.replaceData(after);
411
+ }
412
+ }, {
413
+ immediate: (_b2 = (_a3 = context.attrs["data:immediate"]) != null ? _a3 : options.immediate) != null ? _b2 : true,
414
+ deep: (_d = (_c2 = context.attrs["data:deep"]) != null ? _c2 : options.deep) != null ? _d : true,
415
+ once: (_e = context.attrs["data:once"]) != null ? _e : options.once
416
+ }));
417
+ };
418
+ setTimeout(async () => {
419
+ var _a3;
420
+ if (props.model !== false) {
421
+ if (isFunctionData || isAsyncData) {
422
+ if (!("defaultData" in vue.vnode.props)) {
423
+ console.warn(`${props.modelName}: defaultData is required for promise or function data.`, props.data);
424
+ }
425
+ const [data] = isAsyncData ? await Promise.all([
426
+ isAsyncFunctionData ? props.data() : props.data,
427
+ (_a3 = defer.value) != null ? _a3 : true
428
+ ]) : [props.data];
429
+ track(typeof data === "function" ? data : (() => data));
430
+ } else {
431
+ track((0, import_vue.isRef)(props.data) || (0, import_vue.isReactive)(props.data) ? props.data : () => props.data, { immediate: false });
432
+ }
433
+ }
434
+ });
435
+ setTimeout(async () => {
436
+ var _a3;
437
+ isReady.value = (_a3 = await defer.value) != null ? _a3 : true;
438
+ });
439
+ component.value = [access(component)].reduce((options, parent) => {
286
440
  var _a3;
287
- const diff = { before: import_object_manager.default.on(before).get(), after: import_object_manager.default.on(after).get() };
288
- if (typeof config2.callback === "function") {
289
- model.replaceData((_a3 = config2.callback(diff, { component })) != null ? _a3 : after);
441
+ while (parent) {
442
+ if (typeof parent.setup === "function") {
443
+ options = { parent: options, self: (_a3 = parent.setup(component, options)) != null ? _a3 : {} };
444
+ if (access(parent.$parent).ReactiveView) {
445
+ break;
446
+ } else {
447
+ parent = access(parent.$parent);
448
+ }
449
+ } else {
450
+ break;
451
+ }
452
+ }
453
+ return options;
454
+ }, component.value);
455
+ props.instance.value = typeof props.instance === "function" ? props.instance(component.value) : component.value;
456
+ return (vue2) => {
457
+ var _a3, _b2;
458
+ if (isReady.value) {
459
+ return access(component).template(component, vue2);
290
460
  } else {
291
- model.replaceData(after);
461
+ return (_b2 = (_a3 = context.slots).loading) == null ? void 0 : _b2.call(_a3, { component });
292
462
  }
293
- }, config2.options);
463
+ };
294
464
  };
295
- setTimeout(async () => {
296
- var _a2;
297
- const [data] = await Promise.all([isAsyncFunctionData ? props.data() : props.data, (_a2 = defer.value) != null ? _a2 : true]);
298
- watchDataProp(data);
299
- });
300
- setTimeout(async () => {
301
- var _a2;
302
- isReady.value = (_a2 = await defer.value) != null ? _a2 : true;
303
- });
304
- if (context.attrs["onUpdate:model"]) {
305
- const config2 = typeof context.attrs["onUpdate:model"] === "function" ? {
306
- callback: context.attrs["onUpdate:model"]
307
- } : (_g = context.attrs["onUpdate:model"]) != null ? _g : {};
308
- if (context.attrs["model:log"]) {
309
- console.log(`[ReactiveView]:model`, { config: config2 });
465
+ const current = () => {
466
+ var _a2, _b2, _c2, _d;
467
+ const emit = (after, before) => {
468
+ if (vue && vue.vnode.el) {
469
+ const event = new CustomEvent("data:emit", {
470
+ bubbles: true,
471
+ // Key: allows it to travel up
472
+ composed: true,
473
+ // Key: allows it to cross Shadow DOM boundaries
474
+ detail: { before, after }
475
+ // Payload goes here
476
+ });
477
+ vue.vnode.el.dispatchEvent(event);
478
+ }
479
+ };
480
+ const normalize = (data) => {
481
+ if (props.debug) {
482
+ console.warn(`[ReactiveView]: using beta props data in [${props.modelName}] component`, { vue, data, defaultData, isRef: (0, import_vue.isRef)(data), isReactive: (0, import_vue.isReactive)(data) });
483
+ }
484
+ if ((0, import_vue.isReactive)(data)) {
485
+ return data;
486
+ } else {
487
+ if ((0, import_vue.isRef)(data) || isFunctionData || isAsyncData) {
488
+ return (0, import_vue.reactive)(datatype);
489
+ } else {
490
+ const props2 = "data" in vue.vnode.props;
491
+ try {
492
+ if (["Array", "Object"].includes(data.constructor.name)) {
493
+ return (0, import_vue.reactive)(props2 ? data : datatype);
494
+ } else {
495
+ return (0, import_vue.reactive)(props2 ? { "": data } : datatype);
496
+ }
497
+ } catch (e) {
498
+ return (0, import_vue.reactive)(props2 ? { "": data } : datatype);
499
+ }
500
+ }
501
+ }
502
+ };
503
+ const config = {
504
+ data: props.beta ? normalize((_a2 = vue.vnode.props) == null ? void 0 : _a2.data) : (0, import_vue.reactive)(import_object_manager.default.on(
505
+ isAsyncData || isFunctionData || (0, import_vue.isRef)(props.data) || (0, import_vue.isReactive)(props.data) ? datatype : "data" in vue.vnode.props ? props.data : datatype
506
+ ).clone()),
507
+ defaultData: import_object_manager.default.on(defaultData).clone(),
508
+ notifications: props.notifications,
509
+ subscriptions: props.subscriptions,
510
+ name: props.modelName,
511
+ logging: props.logging
512
+ };
513
+ const model = new Proxy(props.model ? typeof props.model === "function" ? props.model(config) : props.model : new import_data_manager.default(config), {
514
+ get(target, key, receiver) {
515
+ if (["setData", "replaceData"].includes(key.toString())) {
516
+ return (...params) => {
517
+ var _a3;
518
+ const beforeSetData = (_a3 = access(component).beforeSetData) != null ? _a3 : props.beforeSetData;
519
+ if (typeof beforeSetData === "function") {
520
+ const before = import_object_manager.default.on(target.getData());
521
+ const after = params.length ? import_object_manager.default.on(datatype).set(...params) : import_object_manager.default.on(datatype).set(defaultData);
522
+ if (beforeSetData(access(component).diff(before, after), target)) {
523
+ target[key](...params);
524
+ }
525
+ } else {
526
+ target[key](...params);
527
+ }
528
+ return target;
529
+ };
530
+ } else {
531
+ return Reflect.get(target, key, receiver);
532
+ }
533
+ }
534
+ });
535
+ const component = (0, import_vue.ref)({ parent: { self: vue.proxy }, self: { template, model, diff, emit, dataPath: dataPath2, isValid } });
536
+ if (props.debug) {
537
+ console.warn("[ReactiveView]:", { props, context, vue, defer, config, model, component, datatype, defaultData, isValid, isReady, isFunctionData, isAsyncFunctionData, isAsyncData });
310
538
  }
311
- (0, import_vue.watch)(() => model.getData(), (after, before) => {
312
- const diff = { before: import_object_manager.default.on(before).get(), after: import_object_manager.default.on(after).get() };
313
- config2.callback(diff, { component });
314
- }, config2.options);
315
- }
316
- const component = (0, import_vue.ref)({ parent: { self: vue.proxy }, self: { template, model, isValid } });
317
- component.value = [access(component)].reduce((options, parent) => {
318
- var _a2;
319
- while (parent) {
320
- if (typeof parent.setup === "function") {
321
- options = { parent: options, self: (_a2 = parent.setup(component, options)) != null ? _a2 : {} };
322
- if (access(parent.$parent).ReactiveView) {
323
- break;
539
+ const watchDataProp = (dataProp) => {
540
+ var _a3, _b3, _c3, _d2;
541
+ const config2 = typeof context.attrs["onUpdate:data"] === "function" ? { callback: context.attrs["onUpdate:data"] } : {
542
+ callback: (_b3 = ((_a3 = context.attrs["onUpdate:data"]) != null ? _a3 : {}).callback) != null ? _b3 : context.attrs["data:callback"],
543
+ options: Object.assign(__spreadValues(__spreadValues({
544
+ deep: (_c3 = context.attrs["data:deep"]) != null ? _c3 : true
545
+ }, context.attrs["data:immediate"] ? { immediate: context.attrs["data:immediate"] } : {}), context.attrs["data:once"] ? { once: context.attrs["data:once"] } : {}), ((_d2 = context.attrs["onUpdate:data"]) != null ? _d2 : {}).options)
546
+ };
547
+ if (context.attrs["data:log"]) {
548
+ console.warn(`[ReactiveView]:data`, { config: config2, dataProp });
549
+ }
550
+ subscriptions.push((0, import_vue.watch)(isFunctionData || (0, import_vue.isRef)(dataProp) || (0, import_vue.isReactive)(dataProp) ? dataProp : () => dataProp, (after, before) => {
551
+ var _a4;
552
+ if (typeof config2.callback === "function") {
553
+ model.replaceData((_a4 = config2.callback(access(component).diff(import_object_manager.default.on(before), import_object_manager.default.on(after)), { component })) != null ? _a4 : after);
324
554
  } else {
325
- parent = access(parent.$parent);
555
+ model.replaceData(after);
326
556
  }
327
- } else {
328
- break;
557
+ }, config2.options));
558
+ };
559
+ if (context.attrs["onUpdate:model"] || context.attrs["update:model"]) {
560
+ const config2 = typeof context.attrs["onUpdate:model"] === "function" ? {
561
+ callback: context.attrs["onUpdate:model"],
562
+ options: Object.assign(__spreadValues(__spreadValues({
563
+ deep: (_b2 = context.attrs["model:deep"]) != null ? _b2 : true
564
+ }, context.attrs["model:immediate"] ? { immediate: context.attrs["model:immediate"] } : {}), context.attrs["model:once"] ? { once: context.attrs["model:once"] } : {}), ((_c2 = context.attrs["onUpdate:model"]) != null ? _c2 : {}).options)
565
+ } : (_d = context.attrs["onUpdate:model"]) != null ? _d : {};
566
+ if (context.attrs["model:log"]) {
567
+ console.warn(`[ReactiveView]:model`, { config: config2 });
329
568
  }
569
+ subscriptions.push((0, import_vue.watch)(() => import_object_manager.default.on(model.getData()).clone(), (after, before) => {
570
+ config2.callback(access(component).diff(import_object_manager.default.on(before), import_object_manager.default.on(after)), { component });
571
+ }, config2.options));
330
572
  }
331
- return options;
332
- }, component.value);
333
- props.instance.value = typeof props.instance === "function" ? props.instance(component.value) : component.value;
334
- return (vue2) => {
335
- var _a2, _b2;
336
- if (isReady.value) {
337
- return access(component).template(component, vue2);
573
+ if (props.beta) {
574
+ const isRefData = (0, import_vue.isRef)(props.data);
575
+ if (isRefData || isFunctionData || isAsyncData) {
576
+ setTimeout(async () => {
577
+ var _a3, _b3, _c3;
578
+ const [data] = isAsyncData ? await Promise.all([
579
+ isAsyncFunctionData ? props.data() : props.data,
580
+ (_a3 = defer.value) != null ? _a3 : true
581
+ ]) : [props.data];
582
+ subscriptions.push((0, import_vue.watch)(isRefData ? data : isFunctionData ? data : typeof data === "function" ? data : () => data, (after, before) => {
583
+ var _a4;
584
+ if (before !== void 0 || after !== void 0) {
585
+ const callback = context.attrs["data:callback"];
586
+ if (typeof callback === "function") {
587
+ const diff2 = access(component).diff(import_object_manager.default.on(before), import_object_manager.default.on(after));
588
+ model.replaceData((_a4 = callback(diff2, { component })) != null ? _a4 : after);
589
+ } else {
590
+ model.replaceData(after);
591
+ }
592
+ }
593
+ }, {
594
+ immediate: (_b3 = context.attrs["data:immediate"]) != null ? _b3 : true,
595
+ deep: (_c3 = context.attrs["data:deep"]) != null ? _c3 : true,
596
+ once: context.attrs["data:once"]
597
+ }));
598
+ });
599
+ }
338
600
  } else {
339
- return (_b2 = (_a2 = context.slots).loading) == null ? void 0 : _b2.call(_a2, { component });
601
+ setTimeout(async () => {
602
+ var _a3;
603
+ const [data] = await Promise.all([
604
+ isAsyncFunctionData ? props.data() : props.data,
605
+ (_a3 = defer.value) != null ? _a3 : true
606
+ ]);
607
+ watchDataProp(data);
608
+ });
340
609
  }
610
+ setTimeout(async () => {
611
+ var _a3;
612
+ isReady.value = (_a3 = await defer.value) != null ? _a3 : true;
613
+ });
614
+ component.value = [access(component)].reduce((options, parent) => {
615
+ var _a3;
616
+ while (parent) {
617
+ if (typeof parent.setup === "function") {
618
+ options = { parent: options, self: (_a3 = parent.setup(component, options)) != null ? _a3 : {} };
619
+ if (access(parent.$parent).ReactiveView) {
620
+ break;
621
+ } else {
622
+ parent = access(parent.$parent);
623
+ }
624
+ } else {
625
+ break;
626
+ }
627
+ }
628
+ return options;
629
+ }, component.value);
630
+ props.instance.value = typeof props.instance === "function" ? props.instance(component.value) : component.value;
631
+ return (vue2) => {
632
+ var _a3, _b3;
633
+ if (isReady.value) {
634
+ return access(component).template(component, vue2);
635
+ } else {
636
+ return (_b3 = (_a3 = context.slots).loading) == null ? void 0 : _b3.call(_a3, { component });
637
+ }
638
+ };
341
639
  };
640
+ return props.beta === "next" ? beta() : current();
342
641
  }
343
642
  };
344
643
 
345
644
  // src/index.ts
346
645
  var import_vue2 = require("vue");
347
646
  var import_date_fns_tz = require("date-fns-tz");
647
+ var import_tailwind_merge = require("tailwind-merge");
648
+ console.log(`%c[ReactiveView]: ${version}`, "background-color: red; color: yellow;");
348
649
  var index_default = ReactiveView_default;
349
650
  function safeRequest(request) {
350
651
  return new Promise(async (resolve) => {
@@ -374,7 +675,7 @@ function safeRequest(request) {
374
675
  }
375
676
  });
376
677
  }
377
- function getProps(props, param2) {
678
+ function getProps(props = {}, param2) {
378
679
  var _a;
379
680
  const exclude = Array.isArray(param2) || typeof param2 === "string" ? param2 : param2.exclude;
380
681
  const exclusions = (Array.isArray(exclude) ? exclude : [exclude]).join("|");
@@ -418,8 +719,9 @@ function getDate(param1, param2) {
418
719
  return (0, import_date_fns_tz.formatInTimeZone)(datetime(), options.timezone, options.format);
419
720
  }
420
721
  function access(view = {}, alternative) {
722
+ var _a;
421
723
  const resolve = (target) => {
422
- return new Proxy(target, {
724
+ return new Proxy((0, import_vue2.toRaw)(target), {
423
725
  get(target2, key) {
424
726
  const component = { tree: target2 };
425
727
  do {
@@ -440,9 +742,8 @@ function access(view = {}, alternative) {
440
742
  });
441
743
  };
442
744
  try {
443
- const component = typeof view === "function" ? view() : view;
444
- const ref2 = (0, import_vue2.isRef)(component) ? component.value : component;
445
- return resolve(ref2.ReactiveView ? access(ref2.instance) : ref2);
745
+ const component = (_a = (0, import_vue2.unref)(typeof view === "function" ? view() : view)) != null ? _a : {};
746
+ return resolve("instance" in component ? component.instance : component);
446
747
  } catch (e) {
447
748
  return resolve(view);
448
749
  }
@@ -451,29 +752,41 @@ function useSubscription() {
451
752
  const subscriptions = [];
452
753
  const subscription = Subscriptions.get();
453
754
  return {
454
- addSubscription(name2, handler = () => false, data) {
455
- subscription.subscribe(name2, handler, data);
456
- subscriptions.push(() => subscription.unsubscribe(name2));
755
+ addSubscription(name, handler = () => false, data) {
756
+ subscription.subscribe(name, handler, data);
757
+ subscriptions.push(() => subscription.unsubscribe(name));
457
758
  },
458
- replaceSubscription(name2, handler = () => false, data) {
459
- subscription.replace(name2, handler, data);
460
- subscriptions.push(() => subscription.unsubscribe(name2));
759
+ replaceSubscription(name, handler = () => false, data) {
760
+ subscription.replace(name, handler, data);
761
+ subscriptions.push(() => subscription.unsubscribe(name));
461
762
  },
462
763
  removeSubscriptions() {
463
764
  subscriptions.forEach((subscription2) => safeRequest({
464
765
  try: () => subscription2()
465
766
  }));
466
767
  },
467
- removeSubscription(name2) {
468
- subscription.unsubscribe(name2);
768
+ removeSubscription(name) {
769
+ subscription.unsubscribe(name);
469
770
  },
470
- hasSubscription(name2) {
471
- return subscription.hasSubscription(name2);
771
+ hasSubscription(name) {
772
+ return subscription.hasSubscription(name);
472
773
  },
473
774
  subscriptions,
474
775
  subscription
475
776
  };
476
777
  }
778
+ var Prop = ({ default: value, type, validator, required } = {}) => {
779
+ const types1 = Array.isArray(type) ? type : [type != null ? type : Array];
780
+ const types2 = types1.includes(Object) ? types1 : types1.concat(Object);
781
+ return __spreadProps(__spreadValues({}, value ? { default: (0, import_vue2.ref)(value) } : {}), {
782
+ required,
783
+ validator: (value2) => {
784
+ return validator ? validator((0, import_vue2.unref)(value2)) : Array.from(new Set(types2.map((type2) => {
785
+ return typeof type2 === "function" ? type2().constructor.name : type2;
786
+ }))).includes((0, import_vue2.unref)(value2).constructor.name);
787
+ }
788
+ });
789
+ };
477
790
  function StyleParser(styles = {}) {
478
791
  const transform = (style, status = true) => {
479
792
  const remove = style.split(/(-{[^}]+})/);
@@ -525,37 +838,126 @@ var extendVnode = (component, element) => {
525
838
  const vnode = getVnode();
526
839
  return (props = {}, slots) => {
527
840
  var _a;
528
- const _b = getProps((_a = vnode.props) != null ? _a : {}, []), { class: classes, style: styles } = _b, rest = __objRest(_b, ["class", "style"]);
529
- const finalClasses = MergeStyles(classes, typeof props.class === "function" ? props.class(classes) : props.class);
841
+ const isFunctionClass = typeof props.class === "function";
842
+ const isFunctionStyle = typeof props.style === "function";
843
+ const _b = (_a = vnode.props) != null ? _a : {}, { class: classes, style: styles } = _b, rest = __objRest(_b, ["class", "style"]);
844
+ const finalClasses = (0, import_tailwind_merge.twMerge)(isFunctionClass ? "" : classes, MergeStyles(isFunctionClass ? props.class(classes) : props.class).string);
845
+ const finalStyles = MergeStyles(styles, isFunctionStyle ? props.style(styles) : props.style);
530
846
  const functionalProps = Object.entries(props).reduce((props2, [key2, value]) => {
531
- if (![
532
- "class"
533
- /*, "style"*/
534
- ].includes(key2) && typeof value === "function") {
535
- props2[key2] = value(vnode.props[key2]);
847
+ var _a2;
848
+ if (!["class", "style", "setup"].includes(key2) && typeof value === "function") {
849
+ props2[key2] = value((_a2 = vnode.props) == null ? void 0 : _a2[key2]);
536
850
  }
537
851
  return props2;
538
852
  }, props);
539
- const finalProps = Object.assign(rest, functionalProps, {
540
- class: finalClasses
541
- /*, style: finalStyles*/
542
- });
543
- const finalSlots = typeof slots === "function" ? slots(vnode.children) : vnode.children;
544
- return (0, import_vue2.h)(["string", "undefined"].includes(typeof element) ? vnode : element, finalProps, finalSlots);
853
+ const finalProps = Object.assign(rest, functionalProps, { class: finalClasses, style: finalStyles });
854
+ const finalSlots = slots ? typeof slots === "function" ? slots(vnode.children) : slots : vnode.children;
855
+ const finalElement = ["undefined"].includes(typeof element) ? vnode.type : element;
856
+ return (0, import_vue2.h)(finalElement, finalProps, finalSlots);
545
857
  };
546
858
  }
547
859
  });
548
860
  };
861
+ function defineReactiveView(param1, param2) {
862
+ const instance = (0, import_vue2.ref)();
863
+ return (0, import_vue2.defineComponent)({
864
+ name: param1 == null ? void 0 : param1.modelName,
865
+ props: __spreadValues({ setup }, param1 ? param1.props : {}),
866
+ setup() {
867
+ const _a = param1 != null ? param1 : {}, { setup: setup2, props } = _a, rest = __objRest(_a, ["setup", "props"]);
868
+ return (component) => {
869
+ const props2 = Object.entries(rest).reduce((props3, [key, val]) => {
870
+ return Object.assign(props3, { [key]: typeof val === "function" ? val(component, instance) : val });
871
+ }, {});
872
+ const slots = typeof (param1 == null ? void 0 : param1.slots) === "function" ? param1.slots(component) : Array.isArray(param1 == null ? void 0 : param1.slots) ? () => param1.slots : param1 == null ? void 0 : param1.slots;
873
+ return (0, import_vue2.createVNode)(param2 != null ? param2 : ReactiveView_default, __spreadProps(__spreadValues(__spreadValues({}, props2), Object.assign({}, props2, typeof setup2 === "function" ? {
874
+ setup: (self, parent) => setup2(self, parent, component)
875
+ } : {})), {
876
+ instance
877
+ }), slots);
878
+ };
879
+ }
880
+ });
881
+ }
882
+ function showComponent(component, options = {}) {
883
+ var _a;
884
+ if (options.router) {
885
+ console.warn("[ReactiveView]: Deprecated {router} option used with {showComponent()}. \nUse {plugins} option instead.");
886
+ }
887
+ if (!options.key || !document.getElementById(options.key)) {
888
+ const container = options.container || "app-dialogs";
889
+ const dialogs = document.getElementById(container) || document.createElement("div");
890
+ if (!dialogs.hasAttribute("id")) {
891
+ dialogs.setAttribute("id", container);
892
+ document.body.appendChild(dialogs);
893
+ }
894
+ const dialog = document.createElement("div");
895
+ const id = (_a = options.key) != null ? _a : `dialog_${dialogs.children.length + 1}`;
896
+ dialog.setAttribute("id", id);
897
+ dialogs.appendChild(dialog);
898
+ const app = (0, import_vue2.createApp)(
899
+ {
900
+ setup() {
901
+ return () => component;
902
+ }
903
+ },
904
+ {
905
+ __cleanup__: () => {
906
+ document.querySelectorAll(`#${id}`).forEach((element) => element.remove());
907
+ app.unmount();
908
+ }
909
+ }
910
+ );
911
+ if (options.router) {
912
+ return app.use(options.router).mount(`#${id}`);
913
+ } else if (options.plugins) {
914
+ return options.plugins.reduce((app2, plugin) => {
915
+ return app2.use(...Array.isArray(plugin) ? plugin : [plugin]);
916
+ }, app).mount(`#${id}`);
917
+ } else {
918
+ return app.mount(`#${id}`);
919
+ }
920
+ }
921
+ }
922
+ var getData = (component, path, alternative) => {
923
+ const vue = access(component);
924
+ const data = import_object_manager2.default.on(componentState(vue));
925
+ if (path) {
926
+ return data.get(dataPath(vue, path), alternative);
927
+ } else {
928
+ return data.get();
929
+ }
930
+ };
931
+ var setData = (component, data, path) => {
932
+ const vue = access(component);
933
+ const diff = {
934
+ before: import_object_manager2.default.on(componentState(vue)).clone(),
935
+ after: path ? import_object_manager2.default.on(componentState(vue)).set(dataPath(vue, path), data).get() : import_object_manager2.default.on(componentState(vue)).set(data).get()
936
+ };
937
+ return "state" in vue ? diff : vue.$emit("update:state", diff);
938
+ };
939
+ var componentState = (component) => {
940
+ return (0, import_vue2.unref)("state" in component ? component.state : component.$attrs.state);
941
+ };
942
+ var dataPath = (component, path) => {
943
+ return typeof component.$attrs["data:path"] === "function" ? component.$attrs["data:path"](path) : path;
944
+ };
549
945
  // Annotate the CommonJS export names for ESM import in node:
550
946
  0 && (module.exports = {
551
947
  MergeStyles,
948
+ Prop,
552
949
  StyleParser,
553
950
  access,
951
+ dataPath,
952
+ defineReactiveView,
554
953
  extendVnode,
954
+ getData,
555
955
  getDate,
556
956
  getProps,
557
957
  getReactiveViewComponent,
558
958
  safeRequest,
959
+ setData,
559
960
  setup,
961
+ showComponent,
560
962
  useSubscription
561
963
  });