@hybridly/vue 0.10.0-beta.1 → 0.10.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/THIRD-PARTY-LICENSES.md +20 -0
- package/dist/_chunks/chunk.mjs +26 -0
- package/dist/index.d.mts +533 -489
- package/dist/index.mjs +342 -415
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,127 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as __reExport, t as __exportAll } from "./_chunks/chunk.mjs";
|
|
2
2
|
import { can, createRouter, definePlugin, makeUrl, registerHook as registerHook$1, route, route as route$1, router, router as router$1 } from "@hybridly/core";
|
|
3
3
|
import { clone, debounce, debug, merge, random, setValueAtPath, showViewComponentErrorModal, unsetPropertyAtPath } from "@hybridly/utils";
|
|
4
|
+
import qs from "qs";
|
|
5
|
+
import { computed, createApp, defineComponent, getCurrentInstance, h, isRef, nextTick, onUnmounted, reactive, readonly, ref, shallowRef, toRaw, toValue, triggerRef, unref, watch } from "vue";
|
|
4
6
|
import nprogress from "nprogress";
|
|
5
7
|
import { setupDevtoolsPlugin } from "@vue/devtools-api";
|
|
6
|
-
import qs from "qs";
|
|
7
8
|
import { getByPath, setByPath } from "@clickbar/dot-diver";
|
|
8
9
|
import isEqual from "lodash.isequal";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const RouterLink = defineComponent({
|
|
11
|
+
name: "RouterLink",
|
|
12
|
+
setup(_, { slots, attrs }) {
|
|
13
|
+
return (props) => {
|
|
14
|
+
let data = props.data ?? {};
|
|
15
|
+
const preloads = props.preload ?? false;
|
|
16
|
+
const preserveScroll = props.preserveScroll;
|
|
17
|
+
const preserveState = props.preserveState;
|
|
18
|
+
const url = makeUrl(props.href ?? "");
|
|
19
|
+
const method = props.method?.toUpperCase() ?? "GET";
|
|
20
|
+
const as = typeof props.as === "object" ? props.as : props.as?.toLowerCase() ?? "a";
|
|
21
|
+
if (method === "GET") {
|
|
22
|
+
debug.adapter("vue", "Moving data object to URL parameters.");
|
|
23
|
+
url.search = qs.stringify(merge(data, qs.parse(url.search, { ignoreQueryPrefix: true })), {
|
|
24
|
+
encodeValuesOnly: true,
|
|
25
|
+
arrayFormat: "indices"
|
|
26
|
+
});
|
|
27
|
+
data = {};
|
|
28
|
+
}
|
|
29
|
+
if (as === "a" && method !== "GET") debug.adapter("vue", `Creating POST/PUT/PATCH/DELETE <a> links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n<RouterLink href="${url}" method="${method}" as="button">...</RouterLink>`);
|
|
30
|
+
function performPreload(type) {
|
|
31
|
+
if (!preloads) return;
|
|
32
|
+
if (props.external) return;
|
|
33
|
+
if (method !== "GET") return;
|
|
34
|
+
if (type !== "mount" && props.disabled) return;
|
|
35
|
+
if (type === "hover" && preloads === "mount") return;
|
|
36
|
+
if (type === "mount" && preloads !== "mount") return;
|
|
37
|
+
router$1.preload(url, {
|
|
38
|
+
data,
|
|
39
|
+
preserveScroll,
|
|
40
|
+
preserveState,
|
|
41
|
+
...props.options
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
performPreload("mount");
|
|
45
|
+
return h(props.as, {
|
|
46
|
+
...attrs,
|
|
47
|
+
...as === "a" ? { href: url } : {},
|
|
48
|
+
...props.disabled ? { disabled: props.disabled } : {},
|
|
49
|
+
onMouseenter: () => performPreload("hover"),
|
|
50
|
+
onAuxclick: (event) => {
|
|
51
|
+
if (props.disabled) event.preventDefault();
|
|
52
|
+
},
|
|
53
|
+
onClick: (event) => {
|
|
54
|
+
if (props.disabled) {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (props.external) return;
|
|
59
|
+
if (!shouldIntercept(event)) return;
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
router$1.navigate({
|
|
62
|
+
url,
|
|
63
|
+
data,
|
|
64
|
+
method,
|
|
65
|
+
preserveState: method !== "GET",
|
|
66
|
+
...props.options
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}, slots.default ? slots : props.text);
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
props: {
|
|
73
|
+
href: {
|
|
74
|
+
type: String,
|
|
75
|
+
required: false,
|
|
76
|
+
default: void 0
|
|
77
|
+
},
|
|
78
|
+
as: {
|
|
79
|
+
type: [String, Object],
|
|
80
|
+
default: "a"
|
|
81
|
+
},
|
|
82
|
+
method: {
|
|
83
|
+
type: String,
|
|
84
|
+
default: "GET"
|
|
85
|
+
},
|
|
86
|
+
data: {
|
|
87
|
+
type: Object,
|
|
88
|
+
default: () => ({})
|
|
89
|
+
},
|
|
90
|
+
external: {
|
|
91
|
+
type: Boolean,
|
|
92
|
+
default: false
|
|
93
|
+
},
|
|
94
|
+
disabled: {
|
|
95
|
+
type: Boolean,
|
|
96
|
+
default: false
|
|
97
|
+
},
|
|
98
|
+
options: {
|
|
99
|
+
type: Object,
|
|
100
|
+
default: () => ({})
|
|
101
|
+
},
|
|
102
|
+
text: {
|
|
103
|
+
type: String,
|
|
104
|
+
required: false,
|
|
105
|
+
default: void 0
|
|
106
|
+
},
|
|
107
|
+
preload: {
|
|
108
|
+
type: [Boolean, String],
|
|
109
|
+
default: false
|
|
110
|
+
},
|
|
111
|
+
preserveScroll: {
|
|
112
|
+
type: Boolean,
|
|
113
|
+
default: void 0
|
|
114
|
+
},
|
|
115
|
+
preserveState: {
|
|
116
|
+
type: Boolean,
|
|
117
|
+
default: void 0
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
function shouldIntercept(event) {
|
|
122
|
+
const isLink = event.currentTarget.tagName.toLowerCase() === "a";
|
|
123
|
+
return !(event.target && (event?.target).isContentEditable || event.defaultPrevented || isLink && event.which > 1 || isLink && event.altKey || isLink && event.ctrlKey || isLink && event.metaKey || isLink && event.shiftKey);
|
|
124
|
+
}
|
|
14
125
|
function progress(options) {
|
|
15
126
|
const resolved = {
|
|
16
127
|
delay: 250,
|
|
@@ -43,8 +154,8 @@ function progress(options) {
|
|
|
43
154
|
clearTimeout(timeout);
|
|
44
155
|
timeout = setTimeout(() => startProgress(), resolved.delay);
|
|
45
156
|
},
|
|
46
|
-
progress: (progress
|
|
47
|
-
if (nprogress.isStarted() && progress
|
|
157
|
+
progress: (progress) => {
|
|
158
|
+
if (nprogress.isStarted() && progress.percentage) nprogress.set(Math.max(nprogress.status, progress.percentage / 100 * .9));
|
|
48
159
|
},
|
|
49
160
|
after: () => finishProgress()
|
|
50
161
|
});
|
|
@@ -114,9 +225,6 @@ function injectCSS(color) {
|
|
|
114
225
|
`;
|
|
115
226
|
document.head.appendChild(element);
|
|
116
227
|
}
|
|
117
|
-
|
|
118
|
-
//#endregion
|
|
119
|
-
//#region src/stores/dialog.ts
|
|
120
228
|
const DEBUG_KEY = "vue:state:dialog";
|
|
121
229
|
const dialogStore = {
|
|
122
230
|
state: {
|
|
@@ -159,16 +267,7 @@ const dialogStore = {
|
|
|
159
267
|
}
|
|
160
268
|
}
|
|
161
269
|
};
|
|
162
|
-
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region src/stores/mount.ts
|
|
165
|
-
/**
|
|
166
|
-
* These callbacks are run on the first stick after the view component is mounted.
|
|
167
|
-
*/
|
|
168
270
|
const onMountedCallbacks = [];
|
|
169
|
-
|
|
170
|
-
//#endregion
|
|
171
|
-
//#region src/stores/state.ts
|
|
172
271
|
const state = {
|
|
173
272
|
context: shallowRef(),
|
|
174
273
|
view: shallowRef(),
|
|
@@ -192,9 +291,6 @@ const state = {
|
|
|
192
291
|
state.viewKey.value = unref(key);
|
|
193
292
|
}
|
|
194
293
|
};
|
|
195
|
-
|
|
196
|
-
//#endregion
|
|
197
|
-
//#region src/components/wrapper.ts
|
|
198
294
|
const wrapper = defineComponent({
|
|
199
295
|
name: "Hybridly",
|
|
200
296
|
setup() {
|
|
@@ -255,9 +351,6 @@ const wrapper = defineComponent({
|
|
|
255
351
|
};
|
|
256
352
|
}
|
|
257
353
|
});
|
|
258
|
-
|
|
259
|
-
//#endregion
|
|
260
|
-
//#region src/devtools.ts
|
|
261
354
|
const hybridlyStateType = "hybridly";
|
|
262
355
|
const hybridlyEventsTimelineLayerId = "Hybridly";
|
|
263
356
|
function setupDevtools(app) {
|
|
@@ -364,9 +457,6 @@ function setupDevtools(app) {
|
|
|
364
457
|
const devtools = { install(app) {
|
|
365
458
|
if (process.env.NODE_ENV === "development" || __VUE_PROD_DEVTOOLS__) setupDevtools(app);
|
|
366
459
|
} };
|
|
367
|
-
|
|
368
|
-
//#endregion
|
|
369
|
-
//#region src/plugins/view-transition.ts
|
|
370
460
|
function viewTransition() {
|
|
371
461
|
if (!document.startViewTransition) return { name: "view-transition" };
|
|
372
462
|
let domUpdated;
|
|
@@ -389,9 +479,6 @@ function viewTransition() {
|
|
|
389
479
|
}
|
|
390
480
|
};
|
|
391
481
|
}
|
|
392
|
-
|
|
393
|
-
//#endregion
|
|
394
|
-
//#region src/stores/form.ts
|
|
395
482
|
const formStore = {
|
|
396
483
|
defaultConfig: {},
|
|
397
484
|
setDefaultConfig: (config) => {
|
|
@@ -401,12 +488,6 @@ const formStore = {
|
|
|
401
488
|
return clone(formStore.defaultConfig);
|
|
402
489
|
}
|
|
403
490
|
};
|
|
404
|
-
|
|
405
|
-
//#endregion
|
|
406
|
-
//#region src/initialize.ts
|
|
407
|
-
/**
|
|
408
|
-
* Initializes Hybridly's router and context.
|
|
409
|
-
*/
|
|
410
491
|
async function initializeHybridly(options = {}) {
|
|
411
492
|
const resolved = options;
|
|
412
493
|
const { element, payload, resolve } = prepare(resolved);
|
|
@@ -428,18 +509,18 @@ async function initializeHybridly(options = {}) {
|
|
|
428
509
|
onContextUpdate: (context) => {
|
|
429
510
|
state.setContext(context);
|
|
430
511
|
},
|
|
431
|
-
onViewSwap: async (options
|
|
432
|
-
if (options
|
|
433
|
-
onMountedCallbacks.push(() => options
|
|
434
|
-
state.setView(options
|
|
512
|
+
onViewSwap: async (options) => {
|
|
513
|
+
if (options.component) {
|
|
514
|
+
onMountedCallbacks.push(() => options.onMounted?.({ isDialog: false }));
|
|
515
|
+
state.setView(options.component);
|
|
435
516
|
}
|
|
436
|
-
state.setProperties(options
|
|
437
|
-
if (!options
|
|
438
|
-
if (options
|
|
439
|
-
onMountedCallbacks.push(() => options
|
|
440
|
-
dialogStore.setComponent(await resolve(options
|
|
441
|
-
dialogStore.setProperties(options
|
|
442
|
-
dialogStore.setKey(options
|
|
517
|
+
state.setProperties(options.properties);
|
|
518
|
+
if (!options.preserveState && !options.dialog) state.setViewKey(random());
|
|
519
|
+
if (options.dialog) {
|
|
520
|
+
onMountedCallbacks.push(() => options.onMounted?.({ isDialog: true }));
|
|
521
|
+
dialogStore.setComponent(await resolve(options.dialog.component));
|
|
522
|
+
dialogStore.setProperties(options.dialog.properties);
|
|
523
|
+
dialogStore.setKey(options.dialog.key);
|
|
443
524
|
dialogStore.show();
|
|
444
525
|
} else dialogStore.hide();
|
|
445
526
|
}
|
|
@@ -490,13 +571,10 @@ function prepare(options) {
|
|
|
490
571
|
resolve
|
|
491
572
|
};
|
|
492
573
|
}
|
|
493
|
-
/**
|
|
494
|
-
* Resolves a view by its name.
|
|
495
|
-
*/
|
|
496
574
|
async function resolveViewComponent(name, options) {
|
|
497
575
|
const components = options.imported;
|
|
498
576
|
const result = options.components.views.find((view) => name === view.identifier);
|
|
499
|
-
const path = Object.keys(components).sort((a, b) => a.length - b.length).find((path
|
|
577
|
+
const path = Object.keys(components).sort((a, b) => a.length - b.length).find((path) => result ? path.endsWith(result?.path) : false);
|
|
500
578
|
if (!result || !path) {
|
|
501
579
|
console.warn(`View component [${name}] not found. Available components: `, options.components.views.map(({ identifier }) => identifier));
|
|
502
580
|
showViewComponentErrorModal(name);
|
|
@@ -506,133 +584,6 @@ async function resolveViewComponent(name, options) {
|
|
|
506
584
|
component = component.default ?? component;
|
|
507
585
|
return component;
|
|
508
586
|
}
|
|
509
|
-
|
|
510
|
-
//#endregion
|
|
511
|
-
//#region src/components/link.ts
|
|
512
|
-
const RouterLink = defineComponent({
|
|
513
|
-
name: "RouterLink",
|
|
514
|
-
setup(_, { slots, attrs }) {
|
|
515
|
-
return (props) => {
|
|
516
|
-
let data = props.data ?? {};
|
|
517
|
-
const preloads = props.preload ?? false;
|
|
518
|
-
const preserveScroll = props.preserveScroll;
|
|
519
|
-
const preserveState = props.preserveState;
|
|
520
|
-
const url = makeUrl(props.href ?? "");
|
|
521
|
-
const method = props.method?.toUpperCase() ?? "GET";
|
|
522
|
-
const as = typeof props.as === "object" ? props.as : props.as?.toLowerCase() ?? "a";
|
|
523
|
-
if (method === "GET") {
|
|
524
|
-
debug.adapter("vue", "Moving data object to URL parameters.");
|
|
525
|
-
url.search = qs.stringify(merge(data, qs.parse(url.search, { ignoreQueryPrefix: true })), {
|
|
526
|
-
encodeValuesOnly: true,
|
|
527
|
-
arrayFormat: "indices"
|
|
528
|
-
});
|
|
529
|
-
data = {};
|
|
530
|
-
}
|
|
531
|
-
if (as === "a" && method !== "GET") debug.adapter("vue", `Creating POST/PUT/PATCH/DELETE <a> links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n<RouterLink href="${url}" method="${method}" as="button">...</RouterLink>`);
|
|
532
|
-
function performPreload(type) {
|
|
533
|
-
if (!preloads) return;
|
|
534
|
-
if (props.external) return;
|
|
535
|
-
if (method !== "GET") return;
|
|
536
|
-
if (type !== "mount" && props.disabled) return;
|
|
537
|
-
if (type === "hover" && preloads === "mount") return;
|
|
538
|
-
if (type === "mount" && preloads !== "mount") return;
|
|
539
|
-
router$1.preload(url, {
|
|
540
|
-
data,
|
|
541
|
-
preserveScroll,
|
|
542
|
-
preserveState,
|
|
543
|
-
...props.options
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
performPreload("mount");
|
|
547
|
-
return h(props.as, {
|
|
548
|
-
...attrs,
|
|
549
|
-
...as === "a" ? { href: url } : {},
|
|
550
|
-
...props.disabled ? { disabled: props.disabled } : {},
|
|
551
|
-
onMouseenter: () => performPreload("hover"),
|
|
552
|
-
onAuxclick: (event) => {
|
|
553
|
-
if (props.disabled) event.preventDefault();
|
|
554
|
-
},
|
|
555
|
-
onClick: (event) => {
|
|
556
|
-
if (props.disabled) {
|
|
557
|
-
event.preventDefault();
|
|
558
|
-
return;
|
|
559
|
-
}
|
|
560
|
-
if (props.external) return;
|
|
561
|
-
if (!shouldIntercept(event)) return;
|
|
562
|
-
event.preventDefault();
|
|
563
|
-
router$1.navigate({
|
|
564
|
-
url,
|
|
565
|
-
data,
|
|
566
|
-
method,
|
|
567
|
-
preserveState: method !== "GET",
|
|
568
|
-
...props.options
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
}, slots.default ? slots : props.text);
|
|
572
|
-
};
|
|
573
|
-
},
|
|
574
|
-
props: {
|
|
575
|
-
href: {
|
|
576
|
-
type: String,
|
|
577
|
-
required: false,
|
|
578
|
-
default: void 0
|
|
579
|
-
},
|
|
580
|
-
as: {
|
|
581
|
-
type: [String, Object],
|
|
582
|
-
default: "a"
|
|
583
|
-
},
|
|
584
|
-
method: {
|
|
585
|
-
type: String,
|
|
586
|
-
default: "GET"
|
|
587
|
-
},
|
|
588
|
-
data: {
|
|
589
|
-
type: Object,
|
|
590
|
-
default: () => ({})
|
|
591
|
-
},
|
|
592
|
-
external: {
|
|
593
|
-
type: Boolean,
|
|
594
|
-
default: false
|
|
595
|
-
},
|
|
596
|
-
disabled: {
|
|
597
|
-
type: Boolean,
|
|
598
|
-
default: false
|
|
599
|
-
},
|
|
600
|
-
options: {
|
|
601
|
-
type: Object,
|
|
602
|
-
default: () => ({})
|
|
603
|
-
},
|
|
604
|
-
text: {
|
|
605
|
-
type: String,
|
|
606
|
-
required: false,
|
|
607
|
-
default: void 0
|
|
608
|
-
},
|
|
609
|
-
preload: {
|
|
610
|
-
type: [Boolean, String],
|
|
611
|
-
default: false
|
|
612
|
-
},
|
|
613
|
-
preserveScroll: {
|
|
614
|
-
type: Boolean,
|
|
615
|
-
default: void 0
|
|
616
|
-
},
|
|
617
|
-
preserveState: {
|
|
618
|
-
type: Boolean,
|
|
619
|
-
default: void 0
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
function shouldIntercept(event) {
|
|
624
|
-
const isLink = event.currentTarget.tagName.toLowerCase() === "a";
|
|
625
|
-
return !(event.target && (event?.target).isContentEditable || event.defaultPrevented || isLink && event.which > 1 || isLink && event.altKey || isLink && event.ctrlKey || isLink && event.metaKey || isLink && event.shiftKey);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
//#endregion
|
|
629
|
-
//#region src/utils.ts
|
|
630
|
-
/**
|
|
631
|
-
* Converts ref to reactive.
|
|
632
|
-
*
|
|
633
|
-
* @see https://vueuse.org/toReactive
|
|
634
|
-
* @param objectRef A ref of object
|
|
635
|
-
*/
|
|
636
587
|
function toReactive(objectRef) {
|
|
637
588
|
if (!isRef(objectRef)) return reactive(objectRef);
|
|
638
589
|
return reactive(new Proxy({}, {
|
|
@@ -661,29 +612,17 @@ function toReactive(objectRef) {
|
|
|
661
612
|
}
|
|
662
613
|
}));
|
|
663
614
|
}
|
|
664
|
-
|
|
665
|
-
//#endregion
|
|
666
|
-
//#region src/composables/property.ts
|
|
667
|
-
/** Accesses all current properties. */
|
|
668
615
|
function useProperties() {
|
|
669
616
|
return readonly(toReactive(computed(() => state.properties.value)));
|
|
670
617
|
}
|
|
671
|
-
/** Accesses a property with a dot notation. */
|
|
672
618
|
function useProperty(path) {
|
|
673
619
|
return computed(() => getByPath(state.properties.value, path));
|
|
674
620
|
}
|
|
675
|
-
/**
|
|
676
|
-
* Sets the property at the given path to the given value.
|
|
677
|
-
* Note: this helper is experimental and may change in the future.
|
|
678
|
-
*/
|
|
679
621
|
function setProperty(path, value) {
|
|
680
622
|
if (!state.properties.value) return;
|
|
681
623
|
setByPath(state.properties.value, path, toValue(value));
|
|
682
624
|
if (state.context.value?.view.properties) setByPath(state.context.value.view.properties, path, toValue(value));
|
|
683
625
|
}
|
|
684
|
-
|
|
685
|
-
//#endregion
|
|
686
|
-
//#region src/composables/form.ts
|
|
687
626
|
function safeClone(obj) {
|
|
688
627
|
return clone(toRaw(obj));
|
|
689
628
|
}
|
|
@@ -695,39 +634,22 @@ function useForm(options) {
|
|
|
695
634
|
recentlyFailed: void 0,
|
|
696
635
|
recentlySuccessful: void 0
|
|
697
636
|
};
|
|
698
|
-
/** Fields that were initially set up. */
|
|
699
637
|
const initial = safeClone(options.fields);
|
|
700
|
-
/** Fields as they were when loaded. */
|
|
701
638
|
const loaded = safeClone(historyData?.fields ?? options.fields);
|
|
702
|
-
/** Current fields. */
|
|
703
639
|
const fields = reactive(safeClone(loaded));
|
|
704
|
-
/** Validation errors for each field. */
|
|
705
640
|
const errors = ref(historyData?.errors ?? {});
|
|
706
|
-
/** Whether the form is dirty. */
|
|
707
641
|
const isDirty = ref(false);
|
|
708
|
-
/** Whether the submission was recently successful. */
|
|
709
642
|
const recentlySuccessful = ref(false);
|
|
710
|
-
/** Whether the submission is successful. */
|
|
711
643
|
const successful = ref(false);
|
|
712
|
-
/** Whether the submission was recently failed. */
|
|
713
644
|
const recentlyFailed = ref(false);
|
|
714
|
-
/** Whether the submission is failed. */
|
|
715
645
|
const failed = ref(false);
|
|
716
|
-
/** Whether the submission is being processed. */
|
|
717
646
|
const processing = ref(false);
|
|
718
|
-
|
|
719
|
-
const progress$1 = ref();
|
|
720
|
-
/**
|
|
721
|
-
* Sets new initial values for the form, so subsequent resets will use thse values.
|
|
722
|
-
*/
|
|
647
|
+
const progress = ref();
|
|
723
648
|
function setInitial(newInitial) {
|
|
724
649
|
Object.entries(newInitial).forEach(([key, value]) => {
|
|
725
650
|
Reflect.set(initial, key, safeClone(value));
|
|
726
651
|
});
|
|
727
652
|
}
|
|
728
|
-
/**
|
|
729
|
-
* Resets the form's failed and successful flags.
|
|
730
|
-
*/
|
|
731
653
|
function resetSubmissionState() {
|
|
732
654
|
successful.value = false;
|
|
733
655
|
failed.value = false;
|
|
@@ -735,37 +657,25 @@ function useForm(options) {
|
|
|
735
657
|
recentlySuccessful.value = false;
|
|
736
658
|
clearTimeout(timeoutIds.recentlySuccessful);
|
|
737
659
|
clearTimeout(timeoutIds.recentlyFailed);
|
|
738
|
-
progress
|
|
660
|
+
progress.value = void 0;
|
|
739
661
|
}
|
|
740
|
-
/**
|
|
741
|
-
* Resets the fields, errors and submission state.
|
|
742
|
-
*/
|
|
743
662
|
function reset() {
|
|
744
663
|
resetSubmissionState();
|
|
745
664
|
clearErrors();
|
|
746
665
|
resetFields();
|
|
747
666
|
}
|
|
748
|
-
/**
|
|
749
|
-
* Resets the fields to their initial values.
|
|
750
|
-
*/
|
|
751
667
|
function resetFields(...keys) {
|
|
752
668
|
if (keys.length === 0) keys = Object.keys(fields);
|
|
753
669
|
keys.forEach((key) => {
|
|
754
670
|
Reflect.set(fields, key, safeClone(Reflect.get(initial, key)));
|
|
755
671
|
});
|
|
756
672
|
}
|
|
757
|
-
/**
|
|
758
|
-
* Clear the form fields.
|
|
759
|
-
*/
|
|
760
673
|
function clear(...keys) {
|
|
761
674
|
if (keys.length === 0) keys = Object.keys(fields);
|
|
762
675
|
keys.forEach((key) => {
|
|
763
676
|
delete fields[key];
|
|
764
677
|
});
|
|
765
678
|
}
|
|
766
|
-
/**
|
|
767
|
-
* Submits the form.
|
|
768
|
-
*/
|
|
769
679
|
function submit(optionsOverrides) {
|
|
770
680
|
const { fields: _f, key: _k, ...optionsWithoutFields } = options;
|
|
771
681
|
const resolvedOptions = optionsOverrides ? merge(optionsWithoutFields, optionsOverrides, { mergePlainObjects: true }) : optionsWithoutFields;
|
|
@@ -790,7 +700,7 @@ function useForm(options) {
|
|
|
790
700
|
return hooks.start?.(context);
|
|
791
701
|
},
|
|
792
702
|
progress: (incoming, context) => {
|
|
793
|
-
progress
|
|
703
|
+
progress.value = incoming;
|
|
794
704
|
return hooks.progress?.(incoming, context);
|
|
795
705
|
},
|
|
796
706
|
error: (incoming, context) => {
|
|
@@ -810,47 +720,32 @@ function useForm(options) {
|
|
|
810
720
|
return hooks.success?.(payload, context);
|
|
811
721
|
},
|
|
812
722
|
after: (context) => {
|
|
813
|
-
progress
|
|
723
|
+
progress.value = void 0;
|
|
814
724
|
processing.value = false;
|
|
815
725
|
return hooks.after?.(context);
|
|
816
726
|
}
|
|
817
727
|
}
|
|
818
728
|
});
|
|
819
729
|
}
|
|
820
|
-
/**
|
|
821
|
-
* Clears all errors.
|
|
822
|
-
*/
|
|
823
730
|
function clearErrors(...keys) {
|
|
824
731
|
if (keys.length === 0) keys = Object.keys(fields);
|
|
825
732
|
keys.forEach((key) => {
|
|
826
733
|
clearError(key);
|
|
827
734
|
});
|
|
828
735
|
}
|
|
829
|
-
/**
|
|
830
|
-
* Checks if the given keys are dirty in the form.
|
|
831
|
-
*/
|
|
832
736
|
function hasDirty(...keys) {
|
|
833
737
|
if (keys.length === 0) return isDirty.value;
|
|
834
738
|
return keys.some((key) => !isEqual(toRaw(getByPath(fields, key)), toRaw(getByPath(initial, key))));
|
|
835
739
|
}
|
|
836
|
-
/**
|
|
837
|
-
* Clears the given field's error.
|
|
838
|
-
*/
|
|
839
740
|
function clearError(key) {
|
|
840
741
|
unsetPropertyAtPath(errors.value, key);
|
|
841
742
|
}
|
|
842
|
-
/**
|
|
843
|
-
* Sets current errors.
|
|
844
|
-
*/
|
|
845
743
|
function setErrors(incoming) {
|
|
846
744
|
clearErrors();
|
|
847
745
|
Object.entries(incoming).forEach(([path, value]) => {
|
|
848
746
|
setValueAtPath(errors.value, path, value);
|
|
849
747
|
});
|
|
850
748
|
}
|
|
851
|
-
/**
|
|
852
|
-
* Aborts the submission.
|
|
853
|
-
*/
|
|
854
749
|
function abort() {
|
|
855
750
|
router$1.abort();
|
|
856
751
|
}
|
|
@@ -886,7 +781,7 @@ function useForm(options) {
|
|
|
886
781
|
hasErrors: computed(() => Object.values(errors.value ?? {}).length > 0),
|
|
887
782
|
initial,
|
|
888
783
|
loaded,
|
|
889
|
-
progress
|
|
784
|
+
progress,
|
|
890
785
|
isDirty,
|
|
891
786
|
errors,
|
|
892
787
|
processing,
|
|
@@ -896,45 +791,29 @@ function useForm(options) {
|
|
|
896
791
|
recentlyFailed
|
|
897
792
|
});
|
|
898
793
|
}
|
|
899
|
-
|
|
900
|
-
//#endregion
|
|
901
|
-
//#region src/composables/history.ts
|
|
902
|
-
/**
|
|
903
|
-
* Returns a ref with a value saved in the history state through Hybridly.
|
|
904
|
-
* The state is linked to a specific browser history entry.
|
|
905
|
-
*/
|
|
906
794
|
function useHistoryState(key, initial) {
|
|
907
795
|
const value = ref(router$1.history.get(key) ?? initial);
|
|
908
|
-
watch(value, (value
|
|
909
|
-
router$1.history.remember(key, toRaw(value
|
|
796
|
+
watch(value, (value) => {
|
|
797
|
+
router$1.history.remember(key, toRaw(value));
|
|
910
798
|
}, {
|
|
911
799
|
immediate: true,
|
|
912
800
|
deep: true
|
|
913
801
|
});
|
|
914
802
|
return value;
|
|
915
803
|
}
|
|
916
|
-
|
|
917
|
-
//#endregion
|
|
918
|
-
//#region src/composables/back-forward.ts
|
|
919
804
|
function useBackForward(options) {
|
|
920
805
|
const callbacks = [];
|
|
921
|
-
registerHook$1("navigated", (options
|
|
922
|
-
if (options
|
|
806
|
+
registerHook$1("navigated", (options) => {
|
|
807
|
+
if (options.type === "back-forward") {
|
|
923
808
|
callbacks.forEach((fn) => fn(state.context.value));
|
|
924
809
|
callbacks.splice(0, callbacks.length);
|
|
925
810
|
}
|
|
926
811
|
});
|
|
927
|
-
/**
|
|
928
|
-
* Applies the given callback on back-forward navigations.
|
|
929
|
-
*/
|
|
930
812
|
function onBackForward(fn) {
|
|
931
813
|
callbacks.push(fn);
|
|
932
814
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
*/
|
|
936
|
-
function reloadOnBackForward(options$1) {
|
|
937
|
-
onBackForward(() => router$1.reload(options$1));
|
|
815
|
+
function reloadOnBackForward(options) {
|
|
816
|
+
onBackForward(() => router$1.reload(options));
|
|
938
817
|
}
|
|
939
818
|
if (options?.reload) reloadOnBackForward(options.reload === true ? void 0 : options.reload);
|
|
940
819
|
return {
|
|
@@ -942,24 +821,31 @@ function useBackForward(options) {
|
|
|
942
821
|
reloadOnBackForward
|
|
943
822
|
};
|
|
944
823
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
824
|
+
var src_exports = /* @__PURE__ */ __exportAll({});
|
|
825
|
+
import * as import__hybridly_core from "@hybridly/core";
|
|
826
|
+
__reExport(src_exports, import__hybridly_core);
|
|
827
|
+
function createPaginator(paginator, defaultOptions) {
|
|
828
|
+
const isPaginator = (p) => {
|
|
829
|
+
return "links" in p && "meta" in p && "last_page" in p.meta;
|
|
830
|
+
};
|
|
831
|
+
if (isPaginator(paginator)) return {
|
|
832
|
+
...paginator,
|
|
833
|
+
to: (page, options) => {
|
|
834
|
+
const link = paginator.links.find((l) => l.page === page);
|
|
835
|
+
if (link?.url) return src_exports.router.get(link.url, {
|
|
836
|
+
preserveState: true,
|
|
837
|
+
...defaultOptions,
|
|
838
|
+
...options
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
return paginator;
|
|
843
|
+
}
|
|
952
844
|
const registerHook = (hook, fn, options) => {
|
|
953
845
|
const unregister = registerHook$1(hook, fn, options);
|
|
954
846
|
if (getCurrentInstance()) onUnmounted(() => unregister());
|
|
955
847
|
return unregister;
|
|
956
848
|
};
|
|
957
|
-
|
|
958
|
-
//#endregion
|
|
959
|
-
//#region src/composables/dialog.ts
|
|
960
|
-
/**
|
|
961
|
-
* Exposes utilities related to the dialogs.
|
|
962
|
-
*/
|
|
963
849
|
function useDialog() {
|
|
964
850
|
return {
|
|
965
851
|
close: () => router$1.dialog.close(),
|
|
@@ -972,22 +858,69 @@ function useDialog() {
|
|
|
972
858
|
properties: computed(() => state.context.value?.dialog?.properties)
|
|
973
859
|
};
|
|
974
860
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
function
|
|
979
|
-
|
|
861
|
+
function isTextFilter(filter) {
|
|
862
|
+
return filter.type === "text";
|
|
863
|
+
}
|
|
864
|
+
function isDateFilter(filter) {
|
|
865
|
+
return filter.type === "date";
|
|
866
|
+
}
|
|
867
|
+
function isSelectFilter(filter) {
|
|
868
|
+
return filter.type === "select";
|
|
869
|
+
}
|
|
870
|
+
function isTernaryFilter(filter) {
|
|
871
|
+
return filter.type === "ternary";
|
|
872
|
+
}
|
|
873
|
+
function isBooleanFilter(filter) {
|
|
874
|
+
return filter.type === "boolean";
|
|
875
|
+
}
|
|
876
|
+
function isTrashedFilter(filter) {
|
|
877
|
+
return filter.type === "trashed";
|
|
878
|
+
}
|
|
879
|
+
function isCallbackFilter(filter) {
|
|
880
|
+
return filter.type === "callback" || ![
|
|
881
|
+
"text",
|
|
882
|
+
"select",
|
|
883
|
+
"ternary",
|
|
884
|
+
"boolean",
|
|
885
|
+
"trashed"
|
|
886
|
+
].includes(filter.type);
|
|
887
|
+
}
|
|
888
|
+
function useRefinements(input, defaultOptions = {}) {
|
|
889
|
+
const refinements = computed(() => toValue(input));
|
|
980
890
|
const sortsKey = computed(() => refinements.value.keys.sorts);
|
|
981
891
|
const filtersKey = computed(() => refinements.value.keys.filters);
|
|
982
892
|
defaultOptions = {
|
|
983
893
|
replace: false,
|
|
984
894
|
...defaultOptions
|
|
985
895
|
};
|
|
896
|
+
const sorts = computed(() => {
|
|
897
|
+
return refinements.value.sorts.map((sort) => ({
|
|
898
|
+
...sort,
|
|
899
|
+
toggle: (options) => toggleSort(sort.name, options),
|
|
900
|
+
isSorting: (direction) => isSorting(sort.name, direction),
|
|
901
|
+
clear: (options) => clearSorts(options)
|
|
902
|
+
}));
|
|
903
|
+
});
|
|
904
|
+
const filters = computed(() => {
|
|
905
|
+
return refinements.value.filters.map((filter) => ({
|
|
906
|
+
...filter,
|
|
907
|
+
apply: (value, options) => applyFilter(filter.name, value, options),
|
|
908
|
+
clear: (options) => clearFilter(filter.name, options),
|
|
909
|
+
search: (query, options) => searchFilter(filter.name, query, options),
|
|
910
|
+
isSelectFilter: () => isSelectFilter(filter),
|
|
911
|
+
isDateFilter: () => isDateFilter(filter),
|
|
912
|
+
isSearchFilter: () => isTextFilter(filter),
|
|
913
|
+
isTernaryFilter: () => isTernaryFilter(filter),
|
|
914
|
+
isBooleanFilter: () => isBooleanFilter(filter),
|
|
915
|
+
isTrashedFilter: () => isTrashedFilter(filter),
|
|
916
|
+
isCallbackFilter: () => isCallbackFilter(filter)
|
|
917
|
+
}));
|
|
918
|
+
});
|
|
986
919
|
function getSort(name) {
|
|
987
|
-
return
|
|
920
|
+
return sorts.value.find((sort) => sort.name === name);
|
|
988
921
|
}
|
|
989
922
|
function getFilter(name) {
|
|
990
|
-
return
|
|
923
|
+
return filters.value.find((sort) => sort.name === name);
|
|
991
924
|
}
|
|
992
925
|
async function reset(options = {}) {
|
|
993
926
|
return await router$1.reload({
|
|
@@ -1013,6 +946,18 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
|
|
|
1013
946
|
data: { [filtersKey.value]: { [filter]: void 0 } }
|
|
1014
947
|
});
|
|
1015
948
|
}
|
|
949
|
+
async function searchFilter(name, query, options = {}) {
|
|
950
|
+
if (!getFilter(name)) {
|
|
951
|
+
console.warn(`[Refinement] Filter "${name}" does not exist.`);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
if (["", null].includes(query?.toString() || null)) query = void 0;
|
|
955
|
+
return await router$1.reload({
|
|
956
|
+
...defaultOptions,
|
|
957
|
+
...options,
|
|
958
|
+
data: { [filtersKey.value]: { [name]: { search: query } } }
|
|
959
|
+
});
|
|
960
|
+
}
|
|
1016
961
|
async function applyFilter(name, value, options = {}) {
|
|
1017
962
|
const filter = getFilter(name);
|
|
1018
963
|
if (!filter) {
|
|
@@ -1020,10 +965,20 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
|
|
|
1020
965
|
return;
|
|
1021
966
|
}
|
|
1022
967
|
if (["", null].includes(value) || value === filter.default) value = void 0;
|
|
968
|
+
const operator = (() => {
|
|
969
|
+
const operator = options.operator ?? filter.operator;
|
|
970
|
+
if (operator === filter.default_operator) return;
|
|
971
|
+
return operator;
|
|
972
|
+
})();
|
|
1023
973
|
return await router$1.reload({
|
|
1024
974
|
...defaultOptions,
|
|
1025
975
|
...options,
|
|
1026
|
-
data: { [filtersKey.value]: { [name]:
|
|
976
|
+
data: { [filtersKey.value]: { [name]: {
|
|
977
|
+
value,
|
|
978
|
+
search: void 0,
|
|
979
|
+
operator,
|
|
980
|
+
options: options.options ?? void 0
|
|
981
|
+
} } }
|
|
1027
982
|
});
|
|
1028
983
|
}
|
|
1029
984
|
async function clearSorts(options = {}) {
|
|
@@ -1094,18 +1049,10 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
|
|
|
1094
1049
|
}
|
|
1095
1050
|
return {
|
|
1096
1051
|
bindFilter,
|
|
1097
|
-
filters
|
|
1098
|
-
|
|
1099
|
-
apply: (value, options) => applyFilter(filter.name, value, options),
|
|
1100
|
-
clear: (options) => clearFilter(filter.name, options)
|
|
1101
|
-
}))),
|
|
1102
|
-
sorts: toReactive(refinements.value.sorts.map((sort) => ({
|
|
1103
|
-
...sort,
|
|
1104
|
-
toggle: (options) => toggleSort(sort.name, options),
|
|
1105
|
-
isSorting: (direction) => isSorting(sort.name, direction),
|
|
1106
|
-
clear: (options) => clearSorts(options)
|
|
1107
|
-
}))),
|
|
1052
|
+
filters,
|
|
1053
|
+
sorts,
|
|
1108
1054
|
filtersKey,
|
|
1055
|
+
sortsKey,
|
|
1109
1056
|
getFilter,
|
|
1110
1057
|
getSort,
|
|
1111
1058
|
reset,
|
|
@@ -1120,9 +1067,6 @@ function useRefinements(properties, refinementsKeys, defaultOptions = {}) {
|
|
|
1120
1067
|
applyFilter
|
|
1121
1068
|
};
|
|
1122
1069
|
}
|
|
1123
|
-
|
|
1124
|
-
//#endregion
|
|
1125
|
-
//#region src/composables/current-route.ts
|
|
1126
1070
|
const isNavigating = ref(false);
|
|
1127
1071
|
function useRoute() {
|
|
1128
1072
|
const current = ref(router$1.current());
|
|
@@ -1140,68 +1084,48 @@ function useRoute() {
|
|
|
1140
1084
|
matches
|
|
1141
1085
|
};
|
|
1142
1086
|
}
|
|
1143
|
-
|
|
1144
|
-
//#endregion
|
|
1145
|
-
//#region src/composables/bulk-select.ts
|
|
1146
1087
|
function useBulkSelect() {
|
|
1147
1088
|
const selection = ref({
|
|
1148
1089
|
all: false,
|
|
1149
1090
|
only: /* @__PURE__ */ new Set(),
|
|
1150
1091
|
except: /* @__PURE__ */ new Set()
|
|
1151
1092
|
});
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1093
|
+
function toggleAll(force) {
|
|
1094
|
+
if (!selection.value.all || force === true) selectAll();
|
|
1095
|
+
else deselectAll();
|
|
1096
|
+
}
|
|
1155
1097
|
function selectAll() {
|
|
1156
1098
|
selection.value.all = true;
|
|
1157
1099
|
selection.value.only.clear();
|
|
1158
1100
|
selection.value.except.clear();
|
|
1159
1101
|
}
|
|
1160
|
-
/**
|
|
1161
|
-
* Deselects all records.
|
|
1162
|
-
*/
|
|
1163
1102
|
function deselectAll() {
|
|
1164
1103
|
selection.value.all = false;
|
|
1165
1104
|
selection.value.only.clear();
|
|
1166
1105
|
selection.value.except.clear();
|
|
1167
1106
|
}
|
|
1168
|
-
/**
|
|
1169
|
-
* Selects the given records.
|
|
1170
|
-
*/
|
|
1171
1107
|
function select(...records) {
|
|
1172
1108
|
records.forEach((record) => selection.value.except.delete(record));
|
|
1173
1109
|
records.forEach((record) => selection.value.only.add(record));
|
|
1174
1110
|
}
|
|
1175
|
-
/**
|
|
1176
|
-
* Deselects the given records.
|
|
1177
|
-
*/
|
|
1178
1111
|
function deselect(...records) {
|
|
1179
1112
|
records.forEach((record) => selection.value.except.add(record));
|
|
1180
1113
|
records.forEach((record) => selection.value.only.delete(record));
|
|
1181
1114
|
}
|
|
1182
|
-
/**
|
|
1183
|
-
* Toggles selection for the given records.
|
|
1184
|
-
*/
|
|
1185
1115
|
function toggle(record, force) {
|
|
1186
1116
|
if (selected(record) || force === false) return deselect(record);
|
|
1187
1117
|
if (!selected(record) || force === true) return select(record);
|
|
1188
1118
|
}
|
|
1189
|
-
/**
|
|
1190
|
-
* Checks whether the given record is selected.
|
|
1191
|
-
*/
|
|
1192
1119
|
function selected(record) {
|
|
1193
1120
|
if (selection.value.all) return !selection.value.except.has(record);
|
|
1194
1121
|
return selection.value.only.has(record);
|
|
1195
1122
|
}
|
|
1196
|
-
/**
|
|
1197
|
-
* Checks whether all records are selected.
|
|
1198
|
-
*/
|
|
1199
1123
|
const allSelected = computed(() => {
|
|
1200
1124
|
return selection.value.all && selection.value.except.size === 0;
|
|
1201
1125
|
});
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1126
|
+
const anySelected = computed(() => {
|
|
1127
|
+
return selection.value.all || selection.value.only.size > 0;
|
|
1128
|
+
});
|
|
1205
1129
|
function bindCheckbox(key) {
|
|
1206
1130
|
return {
|
|
1207
1131
|
onChange: (event) => {
|
|
@@ -1215,6 +1139,8 @@ function useBulkSelect() {
|
|
|
1215
1139
|
}
|
|
1216
1140
|
return {
|
|
1217
1141
|
allSelected,
|
|
1142
|
+
anySelected,
|
|
1143
|
+
toggleAll,
|
|
1218
1144
|
selectAll,
|
|
1219
1145
|
deselectAll,
|
|
1220
1146
|
select,
|
|
@@ -1225,44 +1151,31 @@ function useBulkSelect() {
|
|
|
1225
1151
|
bindCheckbox
|
|
1226
1152
|
};
|
|
1227
1153
|
}
|
|
1228
|
-
|
|
1229
|
-
//#endregion
|
|
1230
|
-
//#region src/composables/query-parameters.ts
|
|
1231
|
-
/**
|
|
1232
|
-
* Access reactive query parameters.
|
|
1233
|
-
*
|
|
1234
|
-
* @see https://hybridly.dev/api/utils/use-query-parameters.html
|
|
1235
|
-
*/
|
|
1236
1154
|
function useQueryParameters() {
|
|
1237
|
-
const state
|
|
1155
|
+
const state = reactive({});
|
|
1238
1156
|
function updateState() {
|
|
1239
1157
|
const params = new URLSearchParams(window.location.search);
|
|
1240
|
-
const unusedKeys = new Set(Object.keys(state
|
|
1158
|
+
const unusedKeys = new Set(Object.keys(state));
|
|
1241
1159
|
for (const key of params.keys()) {
|
|
1242
1160
|
const paramsForKey = params.getAll(key);
|
|
1243
|
-
state
|
|
1161
|
+
state[key] = paramsForKey.length > 1 ? paramsForKey : params.get(key) || "";
|
|
1244
1162
|
unusedKeys.delete(key);
|
|
1245
1163
|
}
|
|
1246
|
-
Array.from(unusedKeys).forEach((key) => delete state
|
|
1164
|
+
Array.from(unusedKeys).forEach((key) => delete state[key]);
|
|
1247
1165
|
}
|
|
1248
1166
|
updateState();
|
|
1249
1167
|
registerHook$1("navigated", updateState);
|
|
1250
|
-
return state
|
|
1168
|
+
return state;
|
|
1251
1169
|
}
|
|
1252
|
-
/**
|
|
1253
|
-
* Makes the specified query parameter reactive.
|
|
1254
|
-
*
|
|
1255
|
-
* @see https://hybridly.dev/api/utils/use-query-parameter.html
|
|
1256
|
-
*/
|
|
1257
1170
|
function useQueryParameter(name, options = {}) {
|
|
1258
1171
|
const query = useQueryParameters();
|
|
1259
|
-
const transform = (value
|
|
1260
|
-
if (options.transform === "bool") return value
|
|
1261
|
-
else if (options.transform === "number") return Number(value
|
|
1262
|
-
else if (options.transform === "string") return String(value
|
|
1263
|
-
else if (options.transform === "date") return new Date(value
|
|
1264
|
-
else if (typeof options.transform === "function") return options.transform(value
|
|
1265
|
-
return value
|
|
1172
|
+
const transform = (value) => {
|
|
1173
|
+
if (options.transform === "bool") return value === true || value === "true" || value === "1" || value === "yes";
|
|
1174
|
+
else if (options.transform === "number") return Number(value);
|
|
1175
|
+
else if (options.transform === "string") return String(value);
|
|
1176
|
+
else if (options.transform === "date") return new Date(value);
|
|
1177
|
+
else if (typeof options.transform === "function") return options.transform(value);
|
|
1178
|
+
return value;
|
|
1266
1179
|
};
|
|
1267
1180
|
const value = ref();
|
|
1268
1181
|
watch(query, () => {
|
|
@@ -1273,58 +1186,65 @@ function useQueryParameter(name, options = {}) {
|
|
|
1273
1186
|
});
|
|
1274
1187
|
return value;
|
|
1275
1188
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
//#region src/composables/table.ts
|
|
1279
|
-
/**
|
|
1280
|
-
* Provides utilities for working with tables.
|
|
1281
|
-
*/
|
|
1282
|
-
function useTable(props, key, defaultOptions = {}) {
|
|
1283
|
-
const table = computed(() => props[key]);
|
|
1189
|
+
function useTable(input, defaultOptions = {}) {
|
|
1190
|
+
const table = computed(() => toValue(input));
|
|
1284
1191
|
const bulk = useBulkSelect();
|
|
1285
|
-
const refinements = useRefinements(
|
|
1286
|
-
|
|
1287
|
-
* Gets additionnal data to send with the request.
|
|
1288
|
-
*/
|
|
1289
|
-
function getAdditionnalData() {
|
|
1192
|
+
const refinements = useRefinements(() => toValue(input).refinements, defaultOptions);
|
|
1193
|
+
function getAdditionnalData(options) {
|
|
1290
1194
|
const data = {};
|
|
1195
|
+
options = {
|
|
1196
|
+
...defaultOptions,
|
|
1197
|
+
...options
|
|
1198
|
+
};
|
|
1291
1199
|
if (defaultOptions?.includeQueryParameters !== false) Object.assign(data, structuredClone(toRaw(useQueryParameters())));
|
|
1292
|
-
if (
|
|
1200
|
+
if (options?.data) Object.assign(data, options.data);
|
|
1293
1201
|
return data;
|
|
1294
1202
|
}
|
|
1295
|
-
/**
|
|
1296
|
-
* Gets the actual identifier for a record.
|
|
1297
|
-
*/
|
|
1298
1203
|
function getRecordKey(record) {
|
|
1299
1204
|
if (typeof record !== "object") return record;
|
|
1300
1205
|
if (Reflect.has(record, "__hybridId")) return Reflect.get(record, "__hybridId");
|
|
1301
|
-
|
|
1206
|
+
if (!table.value.keyName) throw new Error("Record key cannot be fetched because the table has no defined key.");
|
|
1207
|
+
const value = Reflect.get(record, table.value.keyName);
|
|
1208
|
+
if (typeof value === "object" && Reflect.has(value, "value")) return value.value;
|
|
1209
|
+
return value;
|
|
1210
|
+
}
|
|
1211
|
+
function resolveInlineAction(action) {
|
|
1212
|
+
if (typeof action !== "string") return action;
|
|
1213
|
+
return table.value.inlineActions.find(({ name }) => name === action);
|
|
1214
|
+
}
|
|
1215
|
+
function resolveBulkAction(action) {
|
|
1216
|
+
if (typeof action !== "string") return action;
|
|
1217
|
+
return table.value.bulkActions.find(({ name }) => name === action);
|
|
1302
1218
|
}
|
|
1303
|
-
function
|
|
1304
|
-
|
|
1219
|
+
function getActionUrl(action, table) {
|
|
1220
|
+
if (action.url) return action.url;
|
|
1221
|
+
return route$1(table.endpoint);
|
|
1305
1222
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1223
|
+
async function executeInlineAction(action, options) {
|
|
1224
|
+
const resolvedAction = resolveInlineAction(action);
|
|
1225
|
+
if (!resolvedAction) {
|
|
1226
|
+
console.warn(`Action [${action}] is not defined`);
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1310
1229
|
return await router$1.navigate({
|
|
1311
1230
|
method: "post",
|
|
1312
|
-
url:
|
|
1231
|
+
url: getActionUrl(resolvedAction, table.value),
|
|
1313
1232
|
preserveState: true,
|
|
1314
1233
|
data: {
|
|
1315
|
-
...getAdditionnalData(),
|
|
1234
|
+
...getAdditionnalData(options),
|
|
1316
1235
|
type: "action:inline",
|
|
1317
|
-
action:
|
|
1236
|
+
action: resolvedAction.name,
|
|
1318
1237
|
tableId: table.value.id,
|
|
1319
|
-
recordId: getRecordKey(record)
|
|
1238
|
+
recordId: getRecordKey(options.record)
|
|
1320
1239
|
}
|
|
1321
1240
|
});
|
|
1322
1241
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1242
|
+
async function executeBulkAction(action, options = {}) {
|
|
1243
|
+
const resolvedAction = resolveBulkAction(action);
|
|
1244
|
+
if (!resolvedAction) {
|
|
1245
|
+
console.warn(`Action [${action}] is not defined`);
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1328
1248
|
const filterParameters = refinements.currentFilters().reduce((carry, filter) => {
|
|
1329
1249
|
return {
|
|
1330
1250
|
...carry,
|
|
@@ -1333,12 +1253,12 @@ function useTable(props, key, defaultOptions = {}) {
|
|
|
1333
1253
|
}, {});
|
|
1334
1254
|
return await router$1.navigate({
|
|
1335
1255
|
method: "post",
|
|
1336
|
-
url:
|
|
1256
|
+
url: getActionUrl(resolvedAction, table.value),
|
|
1337
1257
|
preserveState: true,
|
|
1338
1258
|
data: {
|
|
1339
|
-
...getAdditionnalData(),
|
|
1259
|
+
...getAdditionnalData(options),
|
|
1340
1260
|
type: "action:bulk",
|
|
1341
|
-
action:
|
|
1261
|
+
action: resolvedAction.name,
|
|
1342
1262
|
tableId: table.value.id,
|
|
1343
1263
|
all: bulk.selection.value.all,
|
|
1344
1264
|
only: [...bulk.selection.value.only],
|
|
@@ -1346,7 +1266,7 @@ function useTable(props, key, defaultOptions = {}) {
|
|
|
1346
1266
|
[refinements.filtersKey.value]: filterParameters
|
|
1347
1267
|
},
|
|
1348
1268
|
hooks: { after: () => {
|
|
1349
|
-
if (options?.deselect === true ||
|
|
1269
|
+
if (options?.deselect === true || resolvedAction.deselect !== false) bulk.deselectAll();
|
|
1350
1270
|
} }
|
|
1351
1271
|
});
|
|
1352
1272
|
}
|
|
@@ -1358,17 +1278,19 @@ function useTable(props, key, defaultOptions = {}) {
|
|
|
1358
1278
|
isPageSelected: computed(() => table.value.records.length > 0 && table.value.records.every((record) => bulk.selected(getRecordKey(record)))),
|
|
1359
1279
|
isSelected: (record) => bulk.selected(getRecordKey(record)),
|
|
1360
1280
|
allSelected: bulk.allSelected,
|
|
1281
|
+
anySelected: bulk.anySelected,
|
|
1361
1282
|
selection: bulk.selection,
|
|
1362
|
-
bindCheckbox: (key
|
|
1363
|
-
toggle: (record) => bulk.toggle(getRecordKey(record)),
|
|
1283
|
+
bindCheckbox: (key) => bulk.bindCheckbox(key),
|
|
1284
|
+
toggle: (record, force) => bulk.toggle(getRecordKey(record), force),
|
|
1285
|
+
toggleAll: (force) => bulk.toggleAll(force),
|
|
1364
1286
|
select: (record) => bulk.select(getRecordKey(record)),
|
|
1365
1287
|
deselect: (record) => bulk.deselect(getRecordKey(record)),
|
|
1366
1288
|
inlineActions: computed(() => table.value.inlineActions.map((action) => ({
|
|
1367
|
-
execute: (record) => executeInlineAction(action
|
|
1289
|
+
execute: (record) => executeInlineAction(action, { record }),
|
|
1368
1290
|
...action
|
|
1369
1291
|
}))),
|
|
1370
1292
|
bulkActions: computed(() => table.value.bulkActions.map((action) => ({
|
|
1371
|
-
execute: (options) => executeBulkAction(action
|
|
1293
|
+
execute: (options) => executeBulkAction(action, options),
|
|
1372
1294
|
...action
|
|
1373
1295
|
}))),
|
|
1374
1296
|
executeInlineAction,
|
|
@@ -1379,31 +1301,36 @@ function useTable(props, key, defaultOptions = {}) {
|
|
|
1379
1301
|
isSorting: (direction) => refinements.isSorting(column.name, direction),
|
|
1380
1302
|
applyFilter: (value, options) => refinements.applyFilter(column.name, value, options),
|
|
1381
1303
|
clearFilter: (options) => refinements.clearFilter(column.name, options),
|
|
1382
|
-
isSortable: !!refinements.sorts.find((sort) => sort.name === column.name),
|
|
1383
|
-
isFilterable: !!refinements.filters.find((filters) => filters.name === column.name)
|
|
1304
|
+
isSortable: !!refinements.sorts.value.find((sort) => sort.name === column.name),
|
|
1305
|
+
isFilterable: !!refinements.filters.value.find((filters) => filters.name === column.name)
|
|
1384
1306
|
}))),
|
|
1385
|
-
data: computed(() =>
|
|
1386
|
-
return
|
|
1307
|
+
data: computed(() => {
|
|
1308
|
+
return table.value.records.map((record) => {
|
|
1309
|
+
const entries = Object.entries(record).map(([key, value]) => [key, value.value]).filter(([key]) => key !== "__hybridId");
|
|
1310
|
+
if (entries.length === 0) return;
|
|
1311
|
+
return Object.fromEntries(entries);
|
|
1312
|
+
}).filter(Boolean);
|
|
1313
|
+
}),
|
|
1314
|
+
records: computed(() => table.value.records.map((record) => {
|
|
1315
|
+
const entries = Object.entries(record).map(([key, value]) => [key, value.value]).filter(([key]) => key !== "__hybridId");
|
|
1316
|
+
return {
|
|
1317
|
+
record: entries.length > 0 ? Object.fromEntries(entries) : {},
|
|
1318
|
+
key: getRecordKey(record),
|
|
1319
|
+
execute: (action) => executeInlineAction(action, { record: getRecordKey(record) }),
|
|
1320
|
+
actions: table.value.inlineActions.map((action) => ({
|
|
1321
|
+
...action,
|
|
1322
|
+
execute: () => executeInlineAction(action.name, { record: getRecordKey(record) })
|
|
1323
|
+
})),
|
|
1324
|
+
select: () => bulk.select(getRecordKey(record)),
|
|
1325
|
+
deselect: () => bulk.deselect(getRecordKey(record)),
|
|
1326
|
+
toggle: (force) => bulk.toggle(getRecordKey(record), force),
|
|
1327
|
+
selected: bulk.selected(getRecordKey(record)),
|
|
1328
|
+
value: (column) => record[typeof column === "string" ? column : column.name].value,
|
|
1329
|
+
extra: (column, path) => getByPath(record[typeof column === "string" ? column : column.name].extra, path)
|
|
1330
|
+
};
|
|
1387
1331
|
})),
|
|
1388
|
-
|
|
1389
|
-
record: Object.values(record).map((record$1) => record$1.value),
|
|
1390
|
-
key: getRecordKey(record),
|
|
1391
|
-
execute: (action) => executeInlineAction(getActionName(action), getRecordKey(record)),
|
|
1392
|
-
actions: table.value.inlineActions.map((action) => ({
|
|
1393
|
-
...action,
|
|
1394
|
-
execute: () => executeInlineAction(action.name, getRecordKey(record))
|
|
1395
|
-
})),
|
|
1396
|
-
select: () => bulk.select(getRecordKey(record)),
|
|
1397
|
-
deselect: () => bulk.deselect(getRecordKey(record)),
|
|
1398
|
-
toggle: (force) => bulk.toggle(getRecordKey(record), force),
|
|
1399
|
-
selected: bulk.selected(getRecordKey(record)),
|
|
1400
|
-
value: (column) => record[typeof column === "string" ? column : column.name].value,
|
|
1401
|
-
extra: (column, path) => getByPath(record[typeof column === "string" ? column : column.name].extra, path)
|
|
1402
|
-
}))),
|
|
1403
|
-
paginator: computed(() => table.value.paginator),
|
|
1332
|
+
paginator: computed(() => createPaginator(table.value.paginator, defaultOptions)),
|
|
1404
1333
|
...refinements
|
|
1405
1334
|
});
|
|
1406
1335
|
}
|
|
1407
|
-
|
|
1408
|
-
//#endregion
|
|
1409
|
-
export { RouterLink, can, initializeHybridly, registerHook, route, router, setProperty, useBackForward, useBulkSelect, useDialog, useForm, useHistoryState, useProperties, useProperty, useQueryParameter, useQueryParameters, useRefinements, useRoute, useTable };
|
|
1336
|
+
export { RouterLink, can, createPaginator, initializeHybridly, isBooleanFilter, isCallbackFilter, isDateFilter, isSelectFilter, isTernaryFilter, isTextFilter, isTrashedFilter, registerHook, route, router, setProperty, useBackForward, useBulkSelect, useDialog, useForm, useHistoryState, useProperties, useProperty, useQueryParameter, useQueryParameters, useRefinements, useRoute, useTable };
|