@resee-movies/nuxt-ux 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/Card.vue +4 -12
- package/dist/runtime/components/Card.vue.d.ts +1 -4
- package/dist/runtime/components/CardScroller.vue +189 -0
- package/dist/runtime/components/CardScroller.vue.d.ts +36 -0
- package/dist/runtime/components/GlobalHeader.vue +107 -0
- package/dist/runtime/components/GlobalHeader.vue.d.ts +15 -0
- package/dist/runtime/components/GlobalHeaderAnnouncement.vue +49 -0
- package/dist/runtime/components/GlobalHeaderAnnouncement.vue.d.ts +14 -0
- package/dist/runtime/components/Image.vue +37 -24
- package/dist/runtime/components/Image.vue.d.ts +1 -0
- package/dist/runtime/components/ImageBase.vue +6 -13
- package/dist/runtime/components/ImageBase.vue.d.ts +3 -4
- package/dist/runtime/components/LayoutPageRoot.vue +55 -0
- package/dist/runtime/components/LayoutPageRoot.vue.d.ts +21 -0
- package/dist/runtime/components/Message.vue +31 -11
- package/dist/runtime/components/Message.vue.d.ts +4 -3
- package/dist/runtime/components/NotificationContainer.vue +2 -2
- package/dist/runtime/components/ReseeWordLogo.vue +53 -0
- package/dist/runtime/components/ReseeWordLogo.vue.d.ts +12 -0
- package/dist/runtime/components/ScrollPinnedContainer.vue +33 -0
- package/dist/runtime/components/ScrollPinnedContainer.vue.d.ts +14 -0
- package/dist/runtime/components/SuccessSplash.vue +47 -0
- package/dist/runtime/components/SuccessSplash.vue.d.ts +6 -0
- package/dist/runtime/components/form/Form.vue +55 -21
- package/dist/runtime/components/form/Form.vue.d.ts +5 -0
- package/dist/runtime/composables/use-global-header-state.d.ts +10 -0
- package/dist/runtime/composables/use-global-header-state.js +20 -0
- package/dist/runtime/composables/use-load-image.d.ts +1 -1
- package/dist/runtime/composables/use-load-image.js +22 -51
- package/dist/runtime/composables/use-mutable-intersection-observer.d.ts +44 -0
- package/dist/runtime/composables/use-mutable-intersection-observer.js +68 -0
- package/dist/runtime/composables/use-resee-ux.d.ts +5 -0
- package/dist/runtime/composables/use-resee-ux.js +11 -1
- package/dist/runtime/composables/use-two-frame-ref-toggle.d.ts +25 -0
- package/dist/runtime/composables/use-two-frame-ref-toggle.js +24 -0
- package/dist/runtime/utils/validation.d.ts +2 -2
- package/dist/runtime/utils/validation.js +2 -2
- package/package.json +1 -1
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { useNuxtApp } from "#imports";
|
|
2
1
|
import { loadImage } from "@resee-movies/utilities/dom/load-image";
|
|
3
2
|
import { getMediaAssetUrl } from "@resee-movies/utilities/resee/get-media-asset-url";
|
|
4
3
|
import { isString } from "@resee-movies/utilities/strings/is-string";
|
|
5
4
|
import { fromTmdbImageSize } from "@resee-movies/utilities/tmdb/from-tmdb-image-size";
|
|
6
5
|
import { getTmdbImageCache } from "@resee-movies/utilities/tmdb/get-tmdb-image-cache";
|
|
7
6
|
import { getTmdbImageUrl } from "@resee-movies/utilities/tmdb/get-tmdb-image-url";
|
|
8
|
-
import {
|
|
7
|
+
import { isPromiseLike } from "@resee-movies/utilities/objects/is-promise-like";
|
|
9
8
|
import { ref, toRef, toValue, watch } from "vue";
|
|
10
9
|
export function useLoadImage(source, config = {}) {
|
|
11
|
-
const nuxtApp = useNuxtApp();
|
|
12
10
|
const src = ref();
|
|
13
11
|
const key = ref();
|
|
14
12
|
const error = ref();
|
|
@@ -31,77 +29,51 @@ export function useLoadImage(source, config = {}) {
|
|
|
31
29
|
src.value = toValue(config.errorSrc);
|
|
32
30
|
key.value = src.value;
|
|
33
31
|
error.value = new Error('"src" is not defined');
|
|
34
|
-
config.onLoading?.(false);
|
|
35
32
|
config.onError?.(error.value);
|
|
36
33
|
return;
|
|
37
34
|
}
|
|
38
35
|
const loadType = toValue(config.type);
|
|
39
36
|
const imgWidth = toValue(config.width);
|
|
40
|
-
if (import.meta.server || nuxtApp.isHydrating) {
|
|
41
|
-
switch (loadType) {
|
|
42
|
-
case "tmdb": {
|
|
43
|
-
src.value = getTmdbImageUrl(sourceUnwrapped, imgWidth ? toTmdbImageSize(imgWidth) : void 0);
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
case "resee": {
|
|
47
|
-
const filename = toValue(config.friendlyName);
|
|
48
|
-
const reseeConfig = toValue(config.reseeConfig);
|
|
49
|
-
const width = fromTmdbImageSize(imgWidth, { originalIsUndefined: true });
|
|
50
|
-
src.value = getMediaAssetUrl(sourceUnwrapped, filename, { width, format: "webp", ...reseeConfig });
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
default: {
|
|
54
|
-
src.value = sourceUnwrapped;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
loading.value = true;
|
|
58
|
-
key.value = sourceUnwrapped;
|
|
59
|
-
config.onLoading?.(true);
|
|
60
|
-
config.onLoad?.(src.value);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
37
|
if (toValue(config.deferLoad)) {
|
|
64
38
|
return;
|
|
65
39
|
}
|
|
66
|
-
let
|
|
67
|
-
let
|
|
40
|
+
let targetSrc;
|
|
41
|
+
let tempSrc;
|
|
42
|
+
let promise;
|
|
68
43
|
if (loadType === "tmdb") {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
44
|
+
targetSrc = getTmdbImageUrl(sourceUnwrapped, imgWidth);
|
|
45
|
+
const result = getTmdbImageCache().getImage(targetSrc);
|
|
46
|
+
if (isPromiseLike(result)) {
|
|
47
|
+
tempSrc = result.placeholderUrl;
|
|
48
|
+
promise = result;
|
|
49
|
+
}
|
|
72
50
|
} else if (loadType === "resee") {
|
|
73
51
|
const filename = toValue(config.friendlyName);
|
|
74
52
|
const reseeConfig = toValue(config.reseeConfig);
|
|
75
53
|
const width = fromTmdbImageSize(imgWidth, { originalIsUndefined: true });
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
);
|
|
54
|
+
targetSrc = getMediaAssetUrl(sourceUnwrapped, filename, { width, format: "webp", ...reseeConfig });
|
|
55
|
+
promise = loadImage(targetSrc);
|
|
79
56
|
} else {
|
|
80
|
-
|
|
57
|
+
targetSrc = sourceUnwrapped;
|
|
58
|
+
promise = loadImage(targetSrc);
|
|
81
59
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
config.onLoading?.(false);
|
|
60
|
+
src.value = tempSrc ?? targetSrc;
|
|
61
|
+
key.value = tempSrc ?? sourceUnwrapped;
|
|
62
|
+
loading.value = !!promise && !tempSrc;
|
|
63
|
+
bgLoading.value = !!promise && !!tempSrc;
|
|
64
|
+
error.value = void 0;
|
|
65
|
+
if (!promise) {
|
|
89
66
|
config.onLoad?.(src.value);
|
|
90
67
|
return;
|
|
91
68
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
loading.value = !pendingSource;
|
|
95
|
-
bgLoading.value = !!pendingSource;
|
|
96
|
-
config.onLoading?.(true);
|
|
97
|
-
pendingLoader.then(
|
|
69
|
+
config.onLoading?.();
|
|
70
|
+
promise.then(
|
|
98
71
|
(loadedSrc) => {
|
|
99
72
|
src.value = loadedSrc;
|
|
100
73
|
key.value = sourceUnwrapped;
|
|
101
74
|
loading.value = false;
|
|
102
75
|
bgLoading.value = false;
|
|
103
76
|
error.value = void 0;
|
|
104
|
-
config.onLoading?.(false);
|
|
105
77
|
config.onLoad?.(src.value);
|
|
106
78
|
},
|
|
107
79
|
(e) => {
|
|
@@ -110,7 +82,6 @@ export function useLoadImage(source, config = {}) {
|
|
|
110
82
|
loading.value = false;
|
|
111
83
|
bgLoading.value = false;
|
|
112
84
|
error.value = e;
|
|
113
|
-
config.onLoading?.(false);
|
|
114
85
|
config.onError?.(e);
|
|
115
86
|
}
|
|
116
87
|
);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type ConfigurableWindow, type MaybeComputedElementRef, type MaybeElement, type Pausable } from '@vueuse/core';
|
|
2
|
+
import { type ComputedRef, type MaybeRefOrGetter } from 'vue';
|
|
3
|
+
/**
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* This exists solely to support a dynamic `rootMargin` property. The capability will
|
|
7
|
+
* land natively in Vueuse soon, at which time this can be dropped.
|
|
8
|
+
*/
|
|
9
|
+
export interface UseMutableIntersectionObserverOptions extends ConfigurableWindow {
|
|
10
|
+
/**
|
|
11
|
+
* Start the IntersectionObserver immediately on creation
|
|
12
|
+
*
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
immediate?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The Element or Document whose bounds are used as the bounding box
|
|
18
|
+
* when testing for intersection.
|
|
19
|
+
*/
|
|
20
|
+
root?: MaybeComputedElementRef | Document;
|
|
21
|
+
/**
|
|
22
|
+
* A string which specifies a set of offsets to add to the root's
|
|
23
|
+
* bounding_box when calculating intersections.
|
|
24
|
+
*/
|
|
25
|
+
rootMargin?: MaybeRefOrGetter<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Either a single number or an array of numbers between 0.0 and 1.
|
|
28
|
+
* @default 0
|
|
29
|
+
*/
|
|
30
|
+
threshold?: number | number[];
|
|
31
|
+
}
|
|
32
|
+
export interface UseMutableIntersectionObserverReturn extends Pausable {
|
|
33
|
+
isSupported: ComputedRef<boolean>;
|
|
34
|
+
stop: () => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Detects that a target element's visibility.
|
|
38
|
+
*
|
|
39
|
+
* @see https://vueuse.org/useIntersectionObserver
|
|
40
|
+
* @param target
|
|
41
|
+
* @param callback
|
|
42
|
+
* @param options
|
|
43
|
+
*/
|
|
44
|
+
export declare function useMutableIntersectionObserver(target: MaybeComputedElementRef | MaybeRefOrGetter<MaybeElement[]> | MaybeComputedElementRef[], callback: IntersectionObserverCallback, options?: UseMutableIntersectionObserverOptions): UseMutableIntersectionObserverReturn;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultWindow,
|
|
3
|
+
noop,
|
|
4
|
+
notNullish,
|
|
5
|
+
toArray,
|
|
6
|
+
tryOnScopeDispose,
|
|
7
|
+
unrefElement,
|
|
8
|
+
useSupported
|
|
9
|
+
} from "@vueuse/core";
|
|
10
|
+
import { computed, shallowRef, toValue, watch } from "vue";
|
|
11
|
+
export function useMutableIntersectionObserver(target, callback, options = {}) {
|
|
12
|
+
const {
|
|
13
|
+
root,
|
|
14
|
+
rootMargin,
|
|
15
|
+
threshold = 0,
|
|
16
|
+
window = defaultWindow,
|
|
17
|
+
immediate = true
|
|
18
|
+
} = options;
|
|
19
|
+
const isSupported = useSupported(() => window && "IntersectionObserver" in window);
|
|
20
|
+
const targets = computed(() => {
|
|
21
|
+
const _target = toValue(target);
|
|
22
|
+
return toArray(_target).map(unrefElement).filter(notNullish);
|
|
23
|
+
});
|
|
24
|
+
let cleanup = noop;
|
|
25
|
+
const isActive = shallowRef(immediate);
|
|
26
|
+
const stopWatch = isSupported.value ? watch(
|
|
27
|
+
() => [targets.value, unrefElement(root), toValue(rootMargin), isActive.value],
|
|
28
|
+
([targets2, root2, rootMargin2]) => {
|
|
29
|
+
cleanup();
|
|
30
|
+
if (!isActive.value)
|
|
31
|
+
return;
|
|
32
|
+
if (!targets2.length)
|
|
33
|
+
return;
|
|
34
|
+
const observer = new IntersectionObserver(
|
|
35
|
+
callback,
|
|
36
|
+
{
|
|
37
|
+
root: unrefElement(root2),
|
|
38
|
+
rootMargin: rootMargin2,
|
|
39
|
+
threshold
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
targets2.forEach((el) => el && observer.observe(el));
|
|
43
|
+
cleanup = () => {
|
|
44
|
+
observer.disconnect();
|
|
45
|
+
cleanup = noop;
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
{ immediate, flush: "post" }
|
|
49
|
+
) : noop;
|
|
50
|
+
const stop = () => {
|
|
51
|
+
cleanup();
|
|
52
|
+
stopWatch();
|
|
53
|
+
isActive.value = false;
|
|
54
|
+
};
|
|
55
|
+
tryOnScopeDispose(stop);
|
|
56
|
+
return {
|
|
57
|
+
isSupported,
|
|
58
|
+
isActive,
|
|
59
|
+
pause() {
|
|
60
|
+
cleanup();
|
|
61
|
+
isActive.value = false;
|
|
62
|
+
},
|
|
63
|
+
resume() {
|
|
64
|
+
isActive.value = true;
|
|
65
|
+
},
|
|
66
|
+
stop
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
type AppPreferences = {
|
|
2
|
+
dismissNotification?: string;
|
|
3
|
+
};
|
|
1
4
|
/**
|
|
2
5
|
* Provides the ability to manage runtime configuration of the ReSee UX
|
|
3
6
|
* module.
|
|
@@ -22,4 +25,6 @@ export declare function useReseeUx(): {
|
|
|
22
25
|
numOptionsSelected: string;
|
|
23
26
|
};
|
|
24
27
|
};
|
|
28
|
+
preferences: import("#app").CookieRef<AppPreferences>;
|
|
25
29
|
};
|
|
30
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useCookie } from "#imports";
|
|
1
2
|
import { reactive } from "vue";
|
|
2
3
|
const Localization = reactive({
|
|
3
4
|
validation: {
|
|
@@ -18,6 +19,15 @@ const Localization = reactive({
|
|
|
18
19
|
numOptionsSelected: "{count} Item(s) Selected"
|
|
19
20
|
}
|
|
20
21
|
});
|
|
22
|
+
const msInYear = 31536e6;
|
|
21
23
|
export function useReseeUx() {
|
|
22
|
-
|
|
24
|
+
const preferences = useCookie("resee-app-preferences", {
|
|
25
|
+
default: () => ({}),
|
|
26
|
+
secure: true,
|
|
27
|
+
httpOnly: false,
|
|
28
|
+
sameSite: "strict",
|
|
29
|
+
maxAge: msInYear / 1e3,
|
|
30
|
+
expires: new Date(Date.now() + msInYear)
|
|
31
|
+
});
|
|
32
|
+
return { locale: Localization, preferences };
|
|
23
33
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the {@link useTwoFrameRefToggle} composable.
|
|
4
|
+
*
|
|
5
|
+
* - `direction` (default: "one-way"): The order in which the refs will be updated,
|
|
6
|
+
* depending on whether they are being toggled true or false.
|
|
7
|
+
* - `"one-way"`: refA -> refB, always.
|
|
8
|
+
* - `"reverse"`: refA -> refB, if true. refB -> refA, if false.
|
|
9
|
+
* - `defaultValue` (default: false): The initial value to set the refs as.
|
|
10
|
+
*/
|
|
11
|
+
type UseTwoFrameRefToggleOptions = {
|
|
12
|
+
direction?: 'one-way' | 'reverse';
|
|
13
|
+
defaultValue?: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Returns two boolean refs and an `update` method that accepts a boolean that the
|
|
17
|
+
* refs will be updated to. The setting of the ref values is staggered, with one
|
|
18
|
+
* happening one re-paint after the first.
|
|
19
|
+
*
|
|
20
|
+
* Why? This sort of one-two-step can be very useful in certain scenarios - like
|
|
21
|
+
* when CSS properties need to be applied in a specific order (e.x. initial state,
|
|
22
|
+
* and then some kind of transition).
|
|
23
|
+
*/
|
|
24
|
+
export declare function useTwoFrameRefToggle(options?: UseTwoFrameRefToggleOptions): [refA: Ref<boolean>, refB: Ref<boolean>, updateMethod: (value: boolean) => void];
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
export function useTwoFrameRefToggle(options) {
|
|
3
|
+
const refA = ref(options?.defaultValue ?? false);
|
|
4
|
+
const refB = ref(options?.defaultValue ?? false);
|
|
5
|
+
const update = (value) => {
|
|
6
|
+
if (refA.value === value) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const refOrder = !value && options?.direction === "reverse" ? [refB, refA] : [refA, refB];
|
|
10
|
+
refOrder[0].value = value;
|
|
11
|
+
let frameId;
|
|
12
|
+
if (frameId) {
|
|
13
|
+
cancelAnimationFrame(frameId);
|
|
14
|
+
frameId = void 0;
|
|
15
|
+
}
|
|
16
|
+
frameId = requestAnimationFrame(() => {
|
|
17
|
+
frameId = requestAnimationFrame(() => {
|
|
18
|
+
refOrder[1].value = value;
|
|
19
|
+
frameId = void 0;
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
return [refA, refB, update];
|
|
24
|
+
}
|
|
@@ -12,10 +12,10 @@ export type TextInputRequirements = {
|
|
|
12
12
|
minLength?: string | number;
|
|
13
13
|
maxLength?: string | number;
|
|
14
14
|
};
|
|
15
|
-
export declare function createTextValidator(requirements: TextInputRequirements): z.ZodMiniString<string> | z.ZodMiniUnion<readonly [z.ZodMiniNull, z.ZodMiniString<string>]>;
|
|
15
|
+
export declare function createTextValidator(requirements: TextInputRequirements): z.ZodMiniString<string> | z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniNull, z.ZodMiniString<string>]>;
|
|
16
16
|
export type ListInputRequirements = {
|
|
17
17
|
required?: boolean;
|
|
18
18
|
minRequired?: string | number;
|
|
19
19
|
maxRequired?: string | number;
|
|
20
20
|
};
|
|
21
|
-
export declare function createListValidator(requirements: ListInputRequirements): z.ZodMiniArray<z.ZodMiniUnknown> | z.ZodMiniUnion<readonly [z.ZodMiniNull, z.ZodMiniArray<z.ZodMiniUnknown>]>;
|
|
21
|
+
export declare function createListValidator(requirements: ListInputRequirements): z.ZodMiniArray<z.ZodMiniUnknown> | z.ZodMiniUnion<readonly [z.ZodMiniUndefined, z.ZodMiniNull, z.ZodMiniArray<z.ZodMiniUnknown>]>;
|
|
@@ -34,7 +34,7 @@ export function createTextValidator(requirements) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
const stringSchema = z.string(toValidationError(locale.validation.required)).check(z.trim(), ...checkFns);
|
|
37
|
-
return requirements.required ? stringSchema : z.union([z.null(), stringSchema]);
|
|
37
|
+
return requirements.required ? stringSchema : z.union([z.undefined(), z.null(), stringSchema]);
|
|
38
38
|
}
|
|
39
39
|
export function createListValidator(requirements) {
|
|
40
40
|
const { locale } = useReseeUx();
|
|
@@ -52,5 +52,5 @@ export function createListValidator(requirements) {
|
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
const arraySchema = z.array(z.unknown(), toValidationError(locale.validation.required)).check(...checkFns);
|
|
55
|
-
return requirements.required ? arraySchema : z.union([z.null(), arraySchema]);
|
|
55
|
+
return requirements.required ? arraySchema : z.union([z.undefined(), z.null(), arraySchema]);
|
|
56
56
|
}
|
package/package.json
CHANGED