@hybridly/vue 0.1.0-alpha.3 → 0.1.0-alpha.5
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.cjs +34 -14
- package/dist/index.d.ts +28 -15
- package/dist/index.mjs +36 -15
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -56,6 +56,8 @@ const dialogStore = {
|
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
const onMountedCallbacks = [];
|
|
60
|
+
|
|
59
61
|
const state = {
|
|
60
62
|
context: vue.ref(),
|
|
61
63
|
view: vue.shallowRef(),
|
|
@@ -119,10 +121,17 @@ const wrapper = vue.defineComponent({
|
|
|
119
121
|
function renderView() {
|
|
120
122
|
utils.debug.adapter("vue:render:view", "Rendering view.");
|
|
121
123
|
state.view.value.inheritAttrs = !!state.view.value.inheritAttrs;
|
|
122
|
-
return vue.h(state.view.value, {
|
|
124
|
+
return vue.withDirectives(vue.h(state.view.value, {
|
|
123
125
|
...state.properties.value,
|
|
124
126
|
key: state.viewKey.value
|
|
125
|
-
})
|
|
127
|
+
}), [[{
|
|
128
|
+
mounted: () => {
|
|
129
|
+
vue.nextTick(() => {
|
|
130
|
+
utils.debug.adapter("vue:render:view", "Calling mounted callbacks.");
|
|
131
|
+
onMountedCallbacks.pop()?.();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}]]);
|
|
126
135
|
}
|
|
127
136
|
function renderDialog() {
|
|
128
137
|
if (dialogStore.state.component.value && dialogStore.state.properties.value) {
|
|
@@ -279,6 +288,9 @@ async function initializeHybridly(options = {}) {
|
|
|
279
288
|
responseErrorModals: resolved.responseErrorModals ?? process.env.NODE_ENV === "development",
|
|
280
289
|
adapter: {
|
|
281
290
|
resolveComponent: resolve,
|
|
291
|
+
onWaitingForMount: (callback) => {
|
|
292
|
+
onMountedCallbacks.push(callback);
|
|
293
|
+
},
|
|
282
294
|
onDialogClose: async () => {
|
|
283
295
|
dialogStore.hide();
|
|
284
296
|
},
|
|
@@ -512,15 +524,10 @@ function toReactive(objectRef) {
|
|
|
512
524
|
function useProperties() {
|
|
513
525
|
return vue.readonly(toReactive(vue.computed(() => state.context.value?.view.properties)));
|
|
514
526
|
}
|
|
515
|
-
function
|
|
516
|
-
return vue.computed(
|
|
517
|
-
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
function useProperty(path, fallback) {
|
|
521
|
-
return vue.computed(
|
|
522
|
-
() => path.split(".").reduce((o, i) => o[i], state.context.value?.view.properties) ?? fallback
|
|
523
|
-
);
|
|
527
|
+
function useProperty(path) {
|
|
528
|
+
return vue.computed(() => {
|
|
529
|
+
return path.split(".").reduce((o, i) => o?.[i], state.context.value?.view.properties);
|
|
530
|
+
});
|
|
524
531
|
}
|
|
525
532
|
|
|
526
533
|
function useContext() {
|
|
@@ -562,6 +569,14 @@ function useForm(options) {
|
|
|
562
569
|
Reflect.set(fields, key, safeClone(Reflect.get(initial, key)));
|
|
563
570
|
});
|
|
564
571
|
}
|
|
572
|
+
function clear(...keys) {
|
|
573
|
+
if (keys.length === 0) {
|
|
574
|
+
keys = Object.keys(fields);
|
|
575
|
+
}
|
|
576
|
+
keys.forEach((key) => {
|
|
577
|
+
delete fields[key];
|
|
578
|
+
});
|
|
579
|
+
}
|
|
565
580
|
function submit(optionsOverrides) {
|
|
566
581
|
const url = typeof options.url === "function" ? options.url() : options.url;
|
|
567
582
|
const data = typeof options.transform === "function" ? options.transform?.(fields) : fields;
|
|
@@ -599,7 +614,9 @@ function useForm(options) {
|
|
|
599
614
|
},
|
|
600
615
|
success: (payload, context) => {
|
|
601
616
|
clearErrors();
|
|
602
|
-
|
|
617
|
+
if (options?.updateInitials) {
|
|
618
|
+
setInitial(fields);
|
|
619
|
+
}
|
|
603
620
|
if (options?.reset !== false) {
|
|
604
621
|
reset();
|
|
605
622
|
}
|
|
@@ -634,7 +651,10 @@ function useForm(options) {
|
|
|
634
651
|
delete errors.value[key];
|
|
635
652
|
}
|
|
636
653
|
function setErrors(incoming) {
|
|
637
|
-
|
|
654
|
+
clearErrors();
|
|
655
|
+
Object.entries(incoming).forEach(([key, value]) => {
|
|
656
|
+
errors.value[key] = value;
|
|
657
|
+
});
|
|
638
658
|
}
|
|
639
659
|
function abort() {
|
|
640
660
|
core.router.abort();
|
|
@@ -650,6 +670,7 @@ function useForm(options) {
|
|
|
650
670
|
}, { deep: true, immediate: true });
|
|
651
671
|
return vue.reactive({
|
|
652
672
|
reset,
|
|
673
|
+
clear,
|
|
653
674
|
fields,
|
|
654
675
|
abort,
|
|
655
676
|
setErrors,
|
|
@@ -772,4 +793,3 @@ exports.useHistoryState = useHistoryState;
|
|
|
772
793
|
exports.usePaginator = usePaginator;
|
|
773
794
|
exports.useProperties = useProperties;
|
|
774
795
|
exports.useProperty = useProperty;
|
|
775
|
-
exports.useTypedProperty = useTypedProperty;
|
package/dist/index.d.ts
CHANGED
|
@@ -181,16 +181,11 @@ declare const RouterLink: vue.DefineComponent<{
|
|
|
181
181
|
|
|
182
182
|
/** Accesses all current properties. */
|
|
183
183
|
declare function useProperties<T extends object, Global extends GlobalHybridlyProperties>(): vue.DeepReadonly<vue.UnwrapNestedRefs<T & Global>>;
|
|
184
|
-
/**
|
|
185
|
-
* Accesses a property with the given type.
|
|
186
|
-
* @experimental Workaround for not being able to type `useProperty`, might be removed in the future.
|
|
187
|
-
*/
|
|
188
|
-
declare function useTypedProperty<T>(path: string, fallback?: T): ComputedRef<T>;
|
|
189
184
|
/** Accesses a property with a dot notation. */
|
|
190
|
-
declare function useProperty<T = GlobalHybridlyProperties, P extends Path<T> = Path<T
|
|
191
|
-
type PathImpl<T, K extends keyof T> = K extends string ? T[K] extends Record<string, any> ? T[K] extends ArrayLike<any> ? K | `${K}.${PathImpl<T[K]
|
|
185
|
+
declare function useProperty<F = never, T = GlobalHybridlyProperties, P extends Path<T> = Path<T>>(path: [F] extends [never] ? ([P] extends [never] ? string : P) : string): ComputedRef<[F] extends [never] ? ([PathValue<T, P>] extends [never] ? never : PathValue<T, P>) : F>;
|
|
186
|
+
type PathImpl<T, K extends keyof T> = K extends string ? T[K] extends undefined ? undefined : NonNullable<T[K]> extends Record<string, any> ? NonNullable<T[K]> extends ArrayLike<any> ? K | `${K}.${PathImpl<NonNullable<T[K]>, Exclude<keyof NonNullable<T[K]>, keyof any[]>>}` : K | `${K}.${PathImpl<NonNullable<T[K]>, keyof NonNullable<T[K]>>}` : K : never;
|
|
192
187
|
type Path<T> = PathImpl<T, keyof T> | keyof T;
|
|
193
|
-
type PathValue<T, P extends Path<T>> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? Rest extends Path<T[K]> ? PathValue<T[K], Rest> : never : never : P extends keyof T ? T[P] : never;
|
|
188
|
+
type PathValue<T, P extends Path<T>> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? T[K] extends undefined ? undefined : Rest extends Path<T[K]> ? PathValue<T[K], Rest> : Rest extends Path<NonNullable<T[K]>> ? PathValue<NonNullable<T[K]>, Rest> | undefined : never : never : P extends keyof T ? T[P] extends undefined ? undefined : T[P] : never;
|
|
194
189
|
|
|
195
190
|
type MaybePromise<T> = T | Promise<T>;
|
|
196
191
|
|
|
@@ -285,7 +280,7 @@ type BaseUrlTransformable = Partial<Omit<URL, 'searchParams' | 'toJSON' | 'toStr
|
|
|
285
280
|
trailingSlash?: boolean;
|
|
286
281
|
};
|
|
287
282
|
|
|
288
|
-
type ConditionalNavigationOption
|
|
283
|
+
type ConditionalNavigationOption<T extends boolean | string> = T | ((payload: NavigationOptions) => T);
|
|
289
284
|
interface NavigationOptions {
|
|
290
285
|
/** View to navigate to. */
|
|
291
286
|
payload?: HybridPayload;
|
|
@@ -293,13 +288,13 @@ interface NavigationOptions {
|
|
|
293
288
|
* Whether to replace the current history state instead of adding
|
|
294
289
|
* one. This affects the browser's "back" and "forward" features.
|
|
295
290
|
*/
|
|
296
|
-
replace?: ConditionalNavigationOption
|
|
297
|
-
/** Whether to preserve the
|
|
298
|
-
preserveScroll?: ConditionalNavigationOption
|
|
291
|
+
replace?: ConditionalNavigationOption<boolean>;
|
|
292
|
+
/** Whether to preserve the scrollbars positions on the page. */
|
|
293
|
+
preserveScroll?: ConditionalNavigationOption<boolean>;
|
|
299
294
|
/** Whether to preserve the current page component's state. */
|
|
300
|
-
preserveState?: ConditionalNavigationOption
|
|
295
|
+
preserveState?: ConditionalNavigationOption<boolean>;
|
|
301
296
|
/** Whether to preserve the current URL. */
|
|
302
|
-
preserveUrl?: ConditionalNavigationOption
|
|
297
|
+
preserveUrl?: ConditionalNavigationOption<boolean>;
|
|
303
298
|
/**
|
|
304
299
|
* Properties of the given URL to override.
|
|
305
300
|
* @example
|
|
@@ -463,6 +458,8 @@ interface Adapter {
|
|
|
463
458
|
onContextUpdate?: (context: InternalRouterContext) => void;
|
|
464
459
|
/** Called when a dialog is closed. */
|
|
465
460
|
onDialogClose?: (context: InternalRouterContext) => void;
|
|
461
|
+
/** Called when Hybridly is waiting for a component to be mounted. The given callback should be executed after the view component is mounted. */
|
|
462
|
+
onWaitingForMount: (callback: Function) => void;
|
|
466
463
|
}
|
|
467
464
|
interface ResolvedAdapter extends Adapter {
|
|
468
465
|
updateRoutingConfiguration: (routing?: RoutingConfiguration) => void;
|
|
@@ -485,12 +482,28 @@ interface FormOptions<T extends Fields> extends Omit<HybridRequestOptions$1, 'da
|
|
|
485
482
|
fields: T;
|
|
486
483
|
url?: UrlResolvable$1 | (() => UrlResolvable$1);
|
|
487
484
|
key?: string | false;
|
|
485
|
+
/**
|
|
486
|
+
* Defines the delay after which the `recentlySuccessful` and `recentlyFailed` variables are reset to `false`.
|
|
487
|
+
*/
|
|
488
488
|
timeout?: number;
|
|
489
|
+
/**
|
|
490
|
+
* Resets the fields of the form to their initial value after a successful submission.
|
|
491
|
+
* @default true
|
|
492
|
+
*/
|
|
489
493
|
reset?: boolean;
|
|
494
|
+
/**
|
|
495
|
+
* Updates the initial values from the form after a successful submission.
|
|
496
|
+
* @default false
|
|
497
|
+
*/
|
|
498
|
+
updateInitials?: boolean;
|
|
499
|
+
/**
|
|
500
|
+
* Callback executed before the form submission for transforming the fields.
|
|
501
|
+
*/
|
|
490
502
|
transform?: (fields: T) => Fields;
|
|
491
503
|
}
|
|
492
504
|
declare function useForm<T extends Fields = Fields>(options: FormOptions<T>): {
|
|
493
505
|
reset: (...keys: (keyof T)[]) => void;
|
|
506
|
+
clear: (...keys: (keyof T)[]) => void;
|
|
494
507
|
fields: vue.UnwrapRef<vue.UnwrapNestedRefs<T>>;
|
|
495
508
|
abort: () => void;
|
|
496
509
|
setErrors: (incoming: Record<string, string>) => void;
|
|
@@ -645,4 +658,4 @@ declare function useDialog(): {
|
|
|
645
658
|
properties: vue.ComputedRef<Properties | undefined>;
|
|
646
659
|
};
|
|
647
660
|
|
|
648
|
-
export { Layout, RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, resolvePageComponent, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty
|
|
661
|
+
export { Layout, RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, resolvePageComponent, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { shallowRef, ref, unref, triggerRef, defineComponent, toRaw, h, createApp, isRef, reactive, readonly, computed, watch, getCurrentInstance, onUnmounted } from 'vue';
|
|
1
|
+
import { shallowRef, ref, unref, triggerRef, defineComponent, toRaw, h, withDirectives, nextTick, createApp, isRef, reactive, readonly, computed, watch, getCurrentInstance, onUnmounted } from 'vue';
|
|
2
2
|
import { registerHook as registerHook$1, createRouter, makeUrl, router } from '@hybridly/core';
|
|
3
3
|
export { can, route, router } from '@hybridly/core';
|
|
4
4
|
import { debug, random, showDomainsDisabledErrorModal, showPageComponentErrorModal, merge, clone } from '@hybridly/utils';
|
|
@@ -48,6 +48,8 @@ const dialogStore = {
|
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
+
const onMountedCallbacks = [];
|
|
52
|
+
|
|
51
53
|
const state = {
|
|
52
54
|
context: ref(),
|
|
53
55
|
view: shallowRef(),
|
|
@@ -111,10 +113,17 @@ const wrapper = defineComponent({
|
|
|
111
113
|
function renderView() {
|
|
112
114
|
debug.adapter("vue:render:view", "Rendering view.");
|
|
113
115
|
state.view.value.inheritAttrs = !!state.view.value.inheritAttrs;
|
|
114
|
-
return h(state.view.value, {
|
|
116
|
+
return withDirectives(h(state.view.value, {
|
|
115
117
|
...state.properties.value,
|
|
116
118
|
key: state.viewKey.value
|
|
117
|
-
})
|
|
119
|
+
}), [[{
|
|
120
|
+
mounted: () => {
|
|
121
|
+
nextTick(() => {
|
|
122
|
+
debug.adapter("vue:render:view", "Calling mounted callbacks.");
|
|
123
|
+
onMountedCallbacks.pop()?.();
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}]]);
|
|
118
127
|
}
|
|
119
128
|
function renderDialog() {
|
|
120
129
|
if (dialogStore.state.component.value && dialogStore.state.properties.value) {
|
|
@@ -271,6 +280,9 @@ async function initializeHybridly(options = {}) {
|
|
|
271
280
|
responseErrorModals: resolved.responseErrorModals ?? process.env.NODE_ENV === "development",
|
|
272
281
|
adapter: {
|
|
273
282
|
resolveComponent: resolve,
|
|
283
|
+
onWaitingForMount: (callback) => {
|
|
284
|
+
onMountedCallbacks.push(callback);
|
|
285
|
+
},
|
|
274
286
|
onDialogClose: async () => {
|
|
275
287
|
dialogStore.hide();
|
|
276
288
|
},
|
|
@@ -504,15 +516,10 @@ function toReactive(objectRef) {
|
|
|
504
516
|
function useProperties() {
|
|
505
517
|
return readonly(toReactive(computed(() => state.context.value?.view.properties)));
|
|
506
518
|
}
|
|
507
|
-
function
|
|
508
|
-
return computed(
|
|
509
|
-
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
|
-
function useProperty(path, fallback) {
|
|
513
|
-
return computed(
|
|
514
|
-
() => path.split(".").reduce((o, i) => o[i], state.context.value?.view.properties) ?? fallback
|
|
515
|
-
);
|
|
519
|
+
function useProperty(path) {
|
|
520
|
+
return computed(() => {
|
|
521
|
+
return path.split(".").reduce((o, i) => o?.[i], state.context.value?.view.properties);
|
|
522
|
+
});
|
|
516
523
|
}
|
|
517
524
|
|
|
518
525
|
function useContext() {
|
|
@@ -554,6 +561,14 @@ function useForm(options) {
|
|
|
554
561
|
Reflect.set(fields, key, safeClone(Reflect.get(initial, key)));
|
|
555
562
|
});
|
|
556
563
|
}
|
|
564
|
+
function clear(...keys) {
|
|
565
|
+
if (keys.length === 0) {
|
|
566
|
+
keys = Object.keys(fields);
|
|
567
|
+
}
|
|
568
|
+
keys.forEach((key) => {
|
|
569
|
+
delete fields[key];
|
|
570
|
+
});
|
|
571
|
+
}
|
|
557
572
|
function submit(optionsOverrides) {
|
|
558
573
|
const url = typeof options.url === "function" ? options.url() : options.url;
|
|
559
574
|
const data = typeof options.transform === "function" ? options.transform?.(fields) : fields;
|
|
@@ -591,7 +606,9 @@ function useForm(options) {
|
|
|
591
606
|
},
|
|
592
607
|
success: (payload, context) => {
|
|
593
608
|
clearErrors();
|
|
594
|
-
|
|
609
|
+
if (options?.updateInitials) {
|
|
610
|
+
setInitial(fields);
|
|
611
|
+
}
|
|
595
612
|
if (options?.reset !== false) {
|
|
596
613
|
reset();
|
|
597
614
|
}
|
|
@@ -626,7 +643,10 @@ function useForm(options) {
|
|
|
626
643
|
delete errors.value[key];
|
|
627
644
|
}
|
|
628
645
|
function setErrors(incoming) {
|
|
629
|
-
|
|
646
|
+
clearErrors();
|
|
647
|
+
Object.entries(incoming).forEach(([key, value]) => {
|
|
648
|
+
errors.value[key] = value;
|
|
649
|
+
});
|
|
630
650
|
}
|
|
631
651
|
function abort() {
|
|
632
652
|
router.abort();
|
|
@@ -642,6 +662,7 @@ function useForm(options) {
|
|
|
642
662
|
}, { deep: true, immediate: true });
|
|
643
663
|
return reactive({
|
|
644
664
|
reset,
|
|
665
|
+
clear,
|
|
645
666
|
fields,
|
|
646
667
|
abort,
|
|
647
668
|
setErrors,
|
|
@@ -747,4 +768,4 @@ function useDialog() {
|
|
|
747
768
|
};
|
|
748
769
|
}
|
|
749
770
|
|
|
750
|
-
export { RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, resolvePageComponent, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty
|
|
771
|
+
export { RouterLink, defineLayout, defineLayoutProperties, initializeHybridly, registerHook, resolvePageComponent, useBackForward, useContext, useDialog, useForm, useHistoryState, usePaginator, useProperties, useProperty };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridly/vue",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.5",
|
|
4
4
|
"description": "Vue adapter for Hybridly",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hybridly",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"lodash.isequal": "^4.5.0",
|
|
44
44
|
"nprogress": "^0.2.0",
|
|
45
45
|
"qs": "^6.11.0",
|
|
46
|
-
"@hybridly/config": "0.1.0-alpha.
|
|
47
|
-
"@hybridly/core": "0.1.0-alpha.
|
|
48
|
-
"@hybridly/progress-plugin": "0.1.0-alpha.
|
|
49
|
-
"@hybridly/utils": "0.1.0-alpha.
|
|
46
|
+
"@hybridly/config": "0.1.0-alpha.5",
|
|
47
|
+
"@hybridly/core": "0.1.0-alpha.5",
|
|
48
|
+
"@hybridly/progress-plugin": "0.1.0-alpha.5",
|
|
49
|
+
"@hybridly/utils": "0.1.0-alpha.5"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/lodash": "^4.14.191",
|