@resee-movies/nuxt-ux 0.17.0 → 0.19.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@resee-movies/nuxt-ux",
3
3
  "configKey": "ux",
4
- "version": "0.17.0",
4
+ "version": "0.19.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.0"
@@ -10,18 +10,28 @@
10
10
  'header-hidden': hideDrawerContent
11
11
  }"
12
12
  >
13
- <div
14
- ref = "drawerElement"
15
- :class = "slots.subheader ? 'border-b border-b-global-background-accent' : void 0"
16
- >
13
+ <div ref="drawerElement">
17
14
  <LayoutPageColumn>
18
15
  <slot name="default" />
19
16
  </LayoutPageColumn>
17
+
18
+ <div
19
+ v-if = "renderSubheader"
20
+ class = "border-b border-b-global-background-accent"
21
+ />
20
22
  </div>
21
23
 
22
- <div v-if="slots.subheader" ref="subheadElement">
23
- <LayoutPageColumn>
24
- <slot name="subheader" />
24
+ <div v-if="renderSubheader" ref="subheadElement" class="subheader">
25
+ <LayoutPageColumn class="overflow-x-auto styled-scroll">
26
+ <slot name="subheader">
27
+ <TableOfContents
28
+ :toc = "props.subheaderToc ?? headerState.subheaderToc.value"
29
+ class = "flex items-center flex-nowrap"
30
+ link-class = "btn small borderless text-nowrap"
31
+ :min-depth = "2"
32
+ :max-depth = "2"
33
+ />
34
+ </slot>
25
35
  </LayoutPageColumn>
26
36
  </div>
27
37
  </header>
@@ -32,16 +42,20 @@
32
42
  </script>
33
43
 
34
44
  <script setup>
35
- import { ref, useSlots, watch } from "vue";
36
- import { useElementSize, useWindowScroll } from "@vueuse/core";
45
+ import { useHead } from "#imports";
46
+ import { computed, ref, useSlots, watch } from "vue";
47
+ import { useElementSize } from "@vueuse/core";
37
48
  import { useGlobalHeaderState } from "../composables/use-global-header-state";
49
+ import { useReseeWindowScroll } from "../composables/use-resee-window-scroll";
38
50
  import { useTwoFrameRefToggle } from "../composables/use-two-frame-ref-toggle";
39
51
  import LayoutPageColumn from "./LayoutPageColumn.vue";
52
+ import TableOfContents from "./TableOfContents.vue";
40
53
  defineOptions({
41
54
  inheritAttrs: false
42
55
  });
43
56
  const props = defineProps({
44
- drawer: { type: Boolean, required: false, default: true }
57
+ drawer: { type: Boolean, required: false, default: true },
58
+ subheaderToc: { type: Array, required: false }
45
59
  });
46
60
  const slots = useSlots();
47
61
  const rulerElement = ref();
@@ -51,9 +65,23 @@ const subheadElement = ref();
51
65
  const { height: headerHeight } = useElementSize(headerElement);
52
66
  const { height: drawerHeight } = useElementSize(drawerElement);
53
67
  const { height: subheadHeight } = useElementSize(subheadElement);
54
- const { y: windowScrollY } = useWindowScroll();
68
+ const {
69
+ y: windowScrollY,
70
+ source: windowScrollSource
71
+ } = useReseeWindowScroll();
55
72
  const [isHeaderAffixed, doTransitions, updateAffixState] = useTwoFrameRefToggle();
56
73
  const hideDrawerContent = ref(false);
74
+ const headerState = useGlobalHeaderState();
75
+ const renderSubheader = computed(() => {
76
+ return !!(slots.subheader || props.subheaderToc?.length || headerState.subheaderToc.value?.length);
77
+ });
78
+ useHead({
79
+ bodyAttrs: {
80
+ style: () => ({
81
+ "--extra-scroll-margin": subheadHeight.value ? `${subheadHeight.value}px` : ""
82
+ })
83
+ }
84
+ });
57
85
  let backscrollCounter = 0;
58
86
  function disableAffix() {
59
87
  updateAffixState(false);
@@ -73,6 +101,11 @@ const { pause, resume } = watch(windowScrollY, (newScrollY, oldScrollY) => {
73
101
  if (!isHeaderAffixed.value && newScrollY > scrollCeiling + rawDrawerHeight) {
74
102
  return enableAffix();
75
103
  }
104
+ if (!windowScrollSource.value) {
105
+ hideDrawerContent.value = true;
106
+ backscrollCounter = 0;
107
+ return;
108
+ }
76
109
  const scrollDelta = newScrollY - oldScrollY;
77
110
  const isScrollDown = scrollDelta > 0;
78
111
  const negDrawerHeight = rawDrawerHeight * -1;
@@ -83,7 +116,6 @@ const { pause, resume } = watch(windowScrollY, (newScrollY, oldScrollY) => {
83
116
  hideDrawerContent.value = false;
84
117
  }
85
118
  });
86
- const headerState = useGlobalHeaderState();
87
119
  watch(
88
120
  [() => props.drawer, headerHeight, subheadHeight, hideDrawerContent, isHeaderAffixed],
89
121
  () => {
@@ -103,5 +135,5 @@ watch(
103
135
  </script>
104
136
 
105
137
  <style scoped>
106
- .placeholder{height:calc(v-bind(headerHeight)*1px)}.header-affixed{box-shadow:var(--shadow-heavy);left:0;position:fixed;right:0;top:0;transform:translateY(0);z-index:100}.header-affixed.header-transit{transition-duration:calc(var(--default-transition-duration)*2);transition-property:transform,box-shadow;transition-timing-function:var(--default-transition-timing-function)}.header-affixed.header-hidden{box-shadow:none;transform:translateY(calc(v-bind(drawerHeight)*-1px))}
138
+ .placeholder{height:calc(v-bind(headerHeight)*1px)}header{position:relative;z-index:100}.header-affixed{box-shadow:var(--shadow-heavy);left:0;position:fixed;right:0;top:0;transform:translateY(0)}.header-affixed.header-transit{transition-duration:calc(var(--default-transition-duration)*2);transition-property:transform,box-shadow;transition-timing-function:var(--default-transition-timing-function)}.header-affixed.header-hidden{box-shadow:none;transform:translateY(calc(v-bind(drawerHeight)*-1px))}.subheader :deep(.btn){background:transparent;transition:background-color;transition-duration:var(--default-transition-duration);transition-timing-function:var(--default-transition-timing-function)}.subheader :deep(.btn).active{background:var(--color-global-background-accent)}
107
139
  </style>
@@ -1,5 +1,15 @@
1
+ import type { TableOfContentsItem } from './TableOfContents.vue.js';
1
2
  export interface GlobalHeaderProps {
3
+ /**
4
+ * Whether the header will act like a flyout drawer when
5
+ * scrolling upward on the page.
6
+ */
2
7
  drawer?: boolean;
8
+ /**
9
+ * Table of contents objects for the global subheader which
10
+ * will be turned into anchor links.
11
+ */
12
+ subheaderToc?: TableOfContentsItem[];
3
13
  }
4
14
  declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<GlobalHeaderProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<GlobalHeaderProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
5
15
  default?: (props: {}) => any;
@@ -72,18 +72,22 @@ const props = defineProps({
72
72
  beveled: { type: Boolean, required: false },
73
73
  raised: { type: Boolean, required: false }
74
74
  });
75
+ const emits = defineEmits(["loading", "load", "error"]);
75
76
  const isImgLoading = ref(true);
76
77
  const imgHasError = ref(null);
77
78
  function handleLoading() {
78
79
  isImgLoading.value = true;
80
+ emits("loading");
79
81
  }
80
82
  function handleLoaded(src) {
81
83
  isImgLoading.value = false;
82
84
  imgHasError.value = null;
85
+ emits("load", src);
83
86
  }
84
87
  function handleError(err) {
85
88
  isImgLoading.value = false;
86
89
  imgHasError.value = err;
90
+ emits("error", err);
87
91
  }
88
92
  </script>
89
93
 
@@ -7,6 +7,14 @@ export interface ImageProps extends ImageBaseProps, CardProps {
7
7
  glassy?: boolean;
8
8
  scaleToParent?: boolean;
9
9
  }
10
- declare const __VLS_export: import("vue").DefineComponent<ImageProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ImageProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const __VLS_export: import("vue").DefineComponent<ImageProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
11
+ error: (err: unknown) => any;
12
+ load: (src: string | undefined) => any;
13
+ loading: () => any;
14
+ }, string, import("vue").PublicProps, Readonly<ImageProps> & Readonly<{
15
+ onError?: ((err: unknown) => any) | undefined;
16
+ onLoad?: ((src: string | undefined) => any) | undefined;
17
+ onLoading?: (() => any) | undefined;
18
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
19
  declare const _default: typeof __VLS_export;
12
20
  export default _default;
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <div class="image-backdrop" :style="offsetStyles">
3
+ <div :class="['background', props.maskPreset]">
4
+ <slot name="background">
5
+ <Transition name="fade" mode="out-in">
6
+ <LazyImage
7
+ v-if = "props.src && !Array.isArray(props.src)"
8
+ v-bind = "props.singleImageOptions"
9
+ :src = "props.src"
10
+ :width = "props.singleImageOptions?.width ?? 'original'"
11
+ :aspect = "props.singleImageOptions?.aspect ?? 'video'"
12
+ />
13
+
14
+ <LazyImageTiler
15
+ v-else-if = "Array.isArray(props.src)"
16
+ v-bind = "props.multiImageOptions"
17
+ :images = "props.src"
18
+ class = "bg-global-background"
19
+ />
20
+
21
+ <LazyMotionArt
22
+ v-else-if = "!props.src && props.motionArt"
23
+ v-bind = "props.motionArtOptions"
24
+ class = "aspect-video sm:aspect-auto sm:h-screen"
25
+ />
26
+ </Transition>
27
+ </slot>
28
+ </div>
29
+
30
+ <div class="foreground">
31
+ <slot name="default" />
32
+ </div>
33
+ </div>
34
+ </template>
35
+
36
+ <script>
37
+
38
+ </script>
39
+
40
+ <script setup>
41
+ import { computed } from "vue";
42
+ import { useGlobalHeaderState } from "../composables/use-global-header-state";
43
+ import LazyImage from "./Image.vue";
44
+ import LazyImageTiler from "./ImageTiler.vue";
45
+ import LazyMotionArt from "./MotionArt.vue";
46
+ const props = defineProps({
47
+ src: { type: null, required: false, default: void 0 },
48
+ behindHeader: { type: Boolean, required: false, default: true },
49
+ motionArt: { type: Boolean, required: false, default: true },
50
+ maskPreset: { type: [String, Array], required: false, default: void 0 },
51
+ singleImageOptions: { type: Object, required: false, default: void 0 },
52
+ multiImageOptions: { type: Object, required: false, default: void 0 },
53
+ motionArtOptions: { type: Object, required: false }
54
+ });
55
+ const headerState = useGlobalHeaderState();
56
+ const offsetStyles = computed(() => {
57
+ return props.behindHeader ? headerState.offsetFromHeaderStyles.value : void 0;
58
+ });
59
+ const headerOffset = computed(() => {
60
+ return props.behindHeader ? `0px` : `${headerState.headerHeight.value}px`;
61
+ });
62
+ </script>
63
+
64
+ <style scoped>
65
+ .image-backdrop{position:relative}.image-backdrop .foreground{position:relative;z-index:1}.image-backdrop .background{max-height:calc(99vh - v-bind(headerOffset));overflow:clip;position:absolute;top:0;width:100%;z-index:0}
66
+ </style>
@@ -0,0 +1,29 @@
1
+ import type { ImageFileDescriptor } from '@resee-movies/utilities/images/normalize-image-file-descriptor';
2
+ import type { ImageMaskPreset } from '../types/index.js';
3
+ import type { ImageProps } from './Image.vue.js';
4
+ import type { ImageBaseProps } from './ImageBase.vue.js';
5
+ import type { ImageTilerProps } from './ImageTiler.vue.js';
6
+ import type { MotionArtProps } from './MotionArt.vue.js';
7
+ export type SingleImageProps = Omit<ImageBaseProps, 'src' | 'alt' | 'loadStyle'> & Pick<ImageProps, 'defaultIcon' | 'iconSize'>;
8
+ export type MultiImageProps = Omit<ImageTilerProps, 'images' | 'maskPreset'>;
9
+ export interface ImageBackdropProps {
10
+ src?: ImageFileDescriptor | ImageFileDescriptor[] | null | undefined;
11
+ behindHeader?: boolean;
12
+ motionArt?: boolean;
13
+ maskPreset?: ImageMaskPreset | ImageMaskPreset[];
14
+ singleImageOptions?: SingleImageProps;
15
+ multiImageOptions?: MultiImageProps;
16
+ motionArtOptions?: MotionArtProps;
17
+ }
18
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ImageBackdropProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ImageBackdropProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
19
+ background?: (props: {}) => any;
20
+ } & {
21
+ default?: (props: {}) => any;
22
+ }>;
23
+ declare const _default: typeof __VLS_export;
24
+ export default _default;
25
+ type __VLS_WithSlots<T, S> = T & {
26
+ new (): {
27
+ $slots: S;
28
+ };
29
+ };
@@ -1,6 +1,6 @@
1
1
  import type { ImageFileDescriptor } from '@resee-movies/utilities/images/normalize-image-file-descriptor';
2
2
  import type { BreakpointSettings } from '../composables/use-settings-for-breakpoint.js';
3
- import type { HTMLElementClassNames } from '../types/index.js';
3
+ import type { HTMLElementClassNames, ImageMaskPreset } from '../types/index.js';
4
4
  export type ValueOrRange = string | number | [min: number, max: number];
5
5
  export type ImageTilerGridSizeDefinition = {
6
6
  cols: number;
@@ -9,7 +9,6 @@ export type ImageTilerGridSizeDefinition = {
9
9
  gapX?: number;
10
10
  gapY?: number;
11
11
  };
12
- export type ImageMaskPreset = 'image-mask-washout' | 'image-mask-gradient-washout' | 'image-mask-gradient-washout-lite' | 'image-mask-gradient-opacity' | 'image-mask-hero';
13
12
  export declare const DefaultImageTilerGridSizeFallback: {
14
13
  cols: number;
15
14
  rows: number;
@@ -80,5 +80,5 @@ const showTitleBar = computed(
80
80
  </script>
81
81
 
82
82
  <style scoped>
83
- @reference "tailwindcss";@layer components{:global(:root){--page-container-pad-y:calc(var(--page-column-gutter)*2);--page-container-pad-x:var(--page-container-pad-y);--page-container-radius:calc(var(--spacing)*1)}.page-container{--custom-accent-color:v-bind(accentColor);--page-container-accent-color:var(--custom-accent-color,var(--color-global-foreground-accent));background-color:var(--color-global-background);border:1px solid var(--page-container-accent-color);border-radius:var(--page-container-radius);box-shadow:var(--shadow-heavy);padding:var(--page-container-pad-y) var(--page-container-pad-x);transition:border-color;transition-duration:var(--default-transition-duration)}@variant sm{.page-container.glass-effect{backdrop-filter:blur(var(--blur-sm));background-color:color-mix(in srgb-linear,transparent 40%,var(--color-global-background))}}@variant max-sm{.page-container:where(.page-column>.page-container){border-bottom:none;border-left:none;border-radius:0;border-right:none;box-shadow:none;margin-left:calc(var(--page-column-gutter)*-1);margin-right:calc(var(--page-column-gutter)*-1);padding-left:var(--page-column-gutter);padding-right:var(--page-column-gutter)}.page-container:not(.page-container+.page-container):where(.page-column:not(.layout-vista)>.page-container){border-top:none}}}
83
+ @reference "tailwindcss";@layer components{:global(:root){--page-container-pad-y:calc(var(--page-column-gutter)*2);--page-container-pad-x:var(--page-container-pad-y);--page-container-radius:calc(var(--spacing)*1)}.page-container{--custom-accent-color:v-bind(accentColor);--page-container-accent-color:var(--custom-accent-color,var(--color-global-foreground-accent));background-color:var(--color-global-background);border:1px solid var(--page-container-accent-color);border-radius:var(--page-container-radius);box-shadow:var(--shadow-heavy);padding:var(--page-container-pad-y) var(--page-container-pad-x);transition:border-color;transition-duration:var(--default-transition-duration)}@variant sm{.page-container.glass-effect{backdrop-filter:blur(var(--blur-sm));background-color:color-mix(in srgb-linear,transparent 20%,var(--color-global-background))}}@variant max-sm{.page-container:where(.page-column>.page-container){border-bottom:none;border-left:none;border-radius:0;border-right:none;box-shadow:none;margin-left:calc(var(--page-column-gutter)*-1);margin-right:calc(var(--page-column-gutter)*-1);padding-left:var(--page-column-gutter);padding-right:var(--page-column-gutter)}.page-container:not(.page-container+.page-container):where(.page-column:not(.layout-vista)>.page-container){border-top:none}}}
84
84
  </style>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div class="motion-art">
3
+ <div class="spotlight spotlight-1"><div /></div>
4
+ <div class="spotlight spotlight-2"><div /></div>
5
+ <div class="spotlight spotlight-3"><div /></div>
6
+ </div>
7
+ </template>
8
+
9
+ <script>
10
+
11
+ </script>
12
+
13
+ <script setup>
14
+ defineProps({
15
+ primaryColor: { type: String, required: false, default: "var(--color-resee-violet)" },
16
+ secondaryColor: { type: String, required: false, default: "var(--color-resee-orange)" },
17
+ tertiaryColor: { type: String, required: false, default: "var(--color-resee-aqua)" }
18
+ });
19
+ </script>
20
+
21
+ <style scoped>
22
+ @reference "tailwindcss";.motion-art{container-type:size}.spotlight{animation:x var(--speed) linear infinite var(--direction);animation-delay:var(--delay-x);filter:blur(3px);position:absolute}.spotlight>div{animation:y calc(var(--speed)*.7) linear infinite var(--direction),c var(--speed) linear infinite var(--direction);animation-delay:var(--delay-y);background:var(--color);border-radius:100%;height:var(--size);opacity:.5;width:var(--size)}@variant motion-reduce{.spotlight,.spotlight>div{animation-play-state:paused}}@keyframes x{to{filter:blur(10px);transform:translateX(calc(100cqw - var(--size)))}}@keyframes y{to{opacity:.3;transform:translateY(calc(100cqh - var(--size)))}}@keyframes c{33%{background:var(--color-2)}66%{background:var(--color-3)}to{background:var(--color)}}.spotlight-1{--size:20vw;--speed:50s;--direction:alternate;--color:v-bind(primaryColor);--color-2:v-bind(secondaryColor);--color-3:v-bind(tertiaryColor);--delay-x:-7s;--delay-y:-8s}.spotlight-2{--size:10vw;--speed:40s;--direction:alternate;--color:v-bind(secondaryColor);--color-2:v-bind(primaryColor);--color-3:v-bind(tertiaryColor);--delay-x:-30s;--delay-y:-1s}.spotlight-3{--size:30vw;--speed:60s;--direction:alternate-reverse;--color:v-bind(tertiaryColor);--color-2:v-bind(primaryColor);--color-3:v-bind(secondaryColor);--delay-x:-13s;--delay-y:0}
23
+ </style>
@@ -0,0 +1,8 @@
1
+ export interface MotionArtProps {
2
+ primaryColor?: string;
3
+ secondaryColor?: string;
4
+ tertiaryColor?: string;
5
+ }
6
+ declare const __VLS_export: import("vue").DefineComponent<MotionArtProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<MotionArtProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
@@ -1,9 +1,28 @@
1
1
  <template>
2
2
  <ol v-if="props.toc?.length">
3
- <li v-for="entry of props.toc" :key="entry.slug">
4
- <a :href="`#${entry.slug}`" v-html="entry.text" />
5
- <TableOfContents v-if="entry.children.length" :toc="entry.children" />
6
- </li>
3
+ <template v-for="entry of props.toc" :key="entry.slug">
4
+ <li v-if="shouldRenderLevel(entry.level)">
5
+ <NuxtLink
6
+ v-slot = "config"
7
+ :href = "`#${entry.slug}`"
8
+ :custom = "true"
9
+ >
10
+ <a
11
+ v-html = "entry.text"
12
+ :class = "[props.linkClass, { active: mounted && areRoutesStrictEqual(config.route, route) }]"
13
+ :href = "config.href"
14
+ />
15
+ </NuxtLink>
16
+
17
+ <TableOfContents
18
+ v-if = "entry.children?.length && shouldRenderLevel((entry.level ?? 1) + 1)"
19
+ :toc = "entry.children"
20
+ :link-class = "props.linkClass"
21
+ :min-depth = "props.minDepth"
22
+ :max-depth = "props.maxDepth"
23
+ />
24
+ </li>
25
+ </template>
7
26
  </ol>
8
27
  </template>
9
28
 
@@ -12,8 +31,26 @@
12
31
  </script>
13
32
 
14
33
  <script setup>
34
+ import { NuxtLink } from "#components";
35
+ import { useRoute } from "#imports";
36
+ import { onMounted, ref } from "vue";
37
+ import { areRoutesStrictEqual } from "../utils/routing";
15
38
  import TableOfContents from "./TableOfContents.vue";
16
39
  const props = defineProps({
17
- toc: { type: null, required: true }
40
+ toc: { type: null, required: true },
41
+ minDepth: { type: Number, required: false },
42
+ maxDepth: { type: Number, required: false },
43
+ linkClass: { type: null, required: false }
44
+ });
45
+ const route = useRoute();
46
+ const mounted = ref(false);
47
+ onMounted(() => {
48
+ mounted.value = true;
18
49
  });
50
+ function shouldRenderLevel(level) {
51
+ if (!level) {
52
+ return true;
53
+ }
54
+ return (!props.minDepth || props.minDepth <= level) && (!props.maxDepth || props.maxDepth >= level);
55
+ }
19
56
  </script>
@@ -1,6 +1,14 @@
1
1
  import type { TableOfContents as TableOfContentsOptions } from '@resee-movies/utilities/dom/generate-table-of-contents';
2
+ import type { HTMLElementClassNames } from '../types/index.js';
3
+ export type TableOfContentsItem = Partial<TableOfContentsOptions> & {
4
+ text: string;
5
+ slug: string;
6
+ };
2
7
  export type UiTableOfContentsProps = {
3
- toc: TableOfContentsOptions[] | null | undefined;
8
+ toc: TableOfContentsItem[] | null | undefined;
9
+ minDepth?: number;
10
+ maxDepth?: number;
11
+ linkClass?: HTMLElementClassNames;
4
12
  };
5
13
  declare const __VLS_export: import("vue").DefineComponent<UiTableOfContentsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<UiTableOfContentsProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
14
  declare const _default: typeof __VLS_export;
@@ -1,10 +1,61 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ import type { TableOfContentsItem } from '../components/TableOfContents.vue.js';
3
+ /**
4
+ *
5
+ */
6
+ declare function tableOfContents(toc: UseGlobalHeaderStateOptions['tableOfContents']): void;
7
+ /**
8
+ * Configuration for the {@link useGlobalHeaderState} composable.
9
+ */
10
+ export type UseGlobalHeaderStateOptions = {
11
+ tableOfContents?: MaybeRefOrGetter<(TableOfContentsItem | undefined)[] | undefined>;
12
+ };
1
13
  /**
2
14
  * Stateful information about the GlobalHeader component.
3
15
  */
4
- export declare function useGlobalHeaderState(): {
16
+ export declare function useGlobalHeaderState(options?: UseGlobalHeaderStateOptions): {
5
17
  headerHeight: import("vue").Ref<number, number>;
6
18
  subheaderHeight: import("vue").Ref<number, number>;
19
+ subheaderToc: import("vue").Ref<{
20
+ level?: number | undefined;
21
+ text: string;
22
+ slug: string;
23
+ parent?: {
24
+ level: number;
25
+ text: string;
26
+ slug: string;
27
+ parent: /*elided*/ any | undefined;
28
+ children: /*elided*/ any[];
29
+ } | undefined;
30
+ children?: {
31
+ level: number;
32
+ text: string;
33
+ slug: string;
34
+ parent: /*elided*/ any | undefined;
35
+ children: /*elided*/ any[];
36
+ }[] | undefined;
37
+ }[], TableOfContentsItem[] | {
38
+ level?: number | undefined;
39
+ text: string;
40
+ slug: string;
41
+ parent?: {
42
+ level: number;
43
+ text: string;
44
+ slug: string;
45
+ parent: /*elided*/ any | undefined;
46
+ children: /*elided*/ any[];
47
+ } | undefined;
48
+ children?: {
49
+ level: number;
50
+ text: string;
51
+ slug: string;
52
+ parent: /*elided*/ any | undefined;
53
+ children: /*elided*/ any[];
54
+ }[] | undefined;
55
+ }[]>;
56
+ tableOfContents: typeof tableOfContents;
7
57
  isHeaderDrawerEnabled: import("vue").Ref<boolean, boolean>;
8
58
  isHeaderPulledDown: import("vue").Ref<boolean, boolean>;
9
59
  offsetFromHeaderStyles: import("vue").ComputedRef<string[]>;
10
60
  };
61
+ export {};
@@ -1,4 +1,4 @@
1
- import { computed, ref } from "vue";
1
+ import { computed, onScopeDispose, ref, toValue, watch } from "vue";
2
2
  const headerHeight = ref(0);
3
3
  const subheaderHeight = ref(0);
4
4
  const isHeaderDrawerEnabled = ref(true);
@@ -9,10 +9,30 @@ const offsetFromHeaderStyles = computed(() => {
9
9
  `padding-top: ${headerHeight.value}px;`
10
10
  ];
11
11
  });
12
- export function useGlobalHeaderState() {
12
+ const subheaderToc = ref([]);
13
+ function tableOfContents(toc) {
14
+ onScopeDispose(() => {
15
+ subheaderToc.value.length = 0;
16
+ }, true);
17
+ watch(
18
+ () => toValue(toc),
19
+ (entries) => {
20
+ subheaderToc.value.push(
21
+ ...entries?.filter((entry) => !!entry) ?? []
22
+ );
23
+ },
24
+ { immediate: true }
25
+ );
26
+ }
27
+ export function useGlobalHeaderState(options) {
28
+ if (options?.tableOfContents) {
29
+ tableOfContents(options.tableOfContents);
30
+ }
13
31
  return {
14
32
  headerHeight,
15
33
  subheaderHeight,
34
+ subheaderToc,
35
+ tableOfContents,
16
36
  isHeaderDrawerEnabled,
17
37
  isHeaderPulledDown,
18
38
  offsetFromHeaderStyles
@@ -0,0 +1,18 @@
1
+ import { type UseWindowScrollOptions, type UseWindowScrollReturn } from '@vueuse/core';
2
+ import { type Ref } from 'vue';
3
+ export type UseReseeWindowScrollReturn = UseWindowScrollReturn & {
4
+ source: Ref<Event | undefined>;
5
+ };
6
+ /**
7
+ * A specialized implementation of the Vueuse {@link useWindowScroll} composable, which adds
8
+ * the new property `source` to the returned object.
9
+ *
10
+ * The purpose of `source` is to provide a best-effort attempt at identifying _why_ the scroll
11
+ * was initiated. To do this, a series of common user interaction events - _wheel_, _touchmove_,
12
+ * etc. are listened to and correlated with the scroll event.
13
+ *
14
+ * In the case of a scroll **not** being initiated by direct user interaction - e.g. invocation of
15
+ * `window.scrollTo` or the user agent scrolling the page in response to a URL hash change - then
16
+ * `source` will be undefined.
17
+ */
18
+ export declare function useReseeWindowScroll(options?: UseWindowScrollOptions): UseReseeWindowScrollReturn;
@@ -0,0 +1,65 @@
1
+ import {
2
+ useEventListener,
3
+ useWindowScroll
4
+ } from "@vueuse/core";
5
+ import { ref } from "vue";
6
+ const NavigationKeys = [
7
+ "ArrowUp",
8
+ "ArrowDown",
9
+ " ",
10
+ "Spacebar",
11
+ "ArrowRight",
12
+ "ArrowLeft",
13
+ "End",
14
+ "Home",
15
+ "PageDown",
16
+ "PageUp"
17
+ ];
18
+ export function useReseeWindowScroll(options) {
19
+ const scrollSource = ref();
20
+ let scrollEndTimeoutId = void 0;
21
+ function clearScrollEndTimeout() {
22
+ if (scrollEndTimeoutId) {
23
+ clearTimeout(scrollEndTimeoutId);
24
+ scrollEndTimeoutId = void 0;
25
+ }
26
+ }
27
+ function setScrollEndTimeout() {
28
+ clearScrollEndTimeout();
29
+ scrollEndTimeoutId = setTimeout(
30
+ () => {
31
+ scrollSource.value = void 0;
32
+ scrollEndTimeoutId = void 0;
33
+ },
34
+ 250
35
+ );
36
+ }
37
+ useEventListener(["wheel", "touchmove", "keydown", "keyup", "mousedown", "mouseup"], (e) => {
38
+ if (e instanceof KeyboardEvent) {
39
+ if (NavigationKeys.includes(e.key)) {
40
+ setScrollEndTimeout();
41
+ scrollSource.value = e;
42
+ }
43
+ } else if (e.type === "mouseup") {
44
+ clearScrollEndTimeout();
45
+ scrollSource.value = void 0;
46
+ } else {
47
+ setScrollEndTimeout();
48
+ scrollSource.value = e;
49
+ }
50
+ });
51
+ const scrollProps = useWindowScroll({
52
+ ...options,
53
+ onScroll(e) {
54
+ options?.onScroll?.(e);
55
+ clearScrollEndTimeout();
56
+ },
57
+ onStop(e) {
58
+ options?.onStop?.(e);
59
+ if (scrollSource.value?.type !== "mousedown") {
60
+ setScrollEndTimeout();
61
+ }
62
+ }
63
+ });
64
+ return { ...scrollProps, source: scrollSource };
65
+ }
@@ -0,0 +1,43 @@
1
+ import { type Ref } from 'vue';
2
+ import type { RouteLocationResolvedGeneric } from 'vue-router';
3
+ /**
4
+ * Vue Router's `resolve` method creates a RouteLocationResolvedGeneric object,
5
+ * while Vue Router's `currentRoute` ref expects a RouteLocationNormalizedLoadedGeneric
6
+ * object (because of course). There is an inconsistency between the two in that the
7
+ * former's `name` property can be null, while the latter's cannot. This means you
8
+ * cannot directly assign the former to the latter without TS complaining.
9
+ *
10
+ * The exceptionally long name here is a nod to the 50+ other _Location_ types that
11
+ * Vue Route exposes.
12
+ */
13
+ export type RouteLocationResolvedGenericWithNonNullableName = Omit<RouteLocationResolvedGeneric, 'name'> & {
14
+ name: string | undefined;
15
+ };
16
+ /**
17
+ * Options for the `update` method returned by the {@link useUrlHash} composable.
18
+ */
19
+ export type UseUrlHashUpdateOptions = {
20
+ /**
21
+ * Whether to update the hash in a way that will cause the browser
22
+ * to scroll to the identified element (default: false).
23
+ */
24
+ scrollTo?: boolean;
25
+ /**
26
+ * Whether to create a new history entry for the hash - push - or to replace the
27
+ * current (default: replace).
28
+ */
29
+ mode?: 'push' | 'replace';
30
+ };
31
+ /**
32
+ * The return type of the {@link useUrlHash} composable.
33
+ */
34
+ export type UseUrlHashReturn = {
35
+ value: Readonly<Ref<string | undefined>>;
36
+ update: (newHash: string | undefined, options?: UseUrlHashUpdateOptions) => boolean;
37
+ };
38
+ /**
39
+ * Read/Write the current URL hash value. By default, this will be done in a way that does
40
+ * not cause browser scroll to behavior to occur - very useful when updating the hash
41
+ * based on the scroll position of the page.
42
+ */
43
+ export declare function useUrlHash(): UseUrlHashReturn;
@@ -0,0 +1,25 @@
1
+ import { useRouter } from "#imports";
2
+ import { isString } from "@resee-movies/utilities/strings/is-string";
3
+ import { computed } from "vue";
4
+ export function useUrlHash() {
5
+ const router = useRouter();
6
+ const value = computed(() => {
7
+ return router.currentRoute.value.hash || void 0;
8
+ });
9
+ const update = (newHash, options) => {
10
+ const normalizedHash = isString(newHash, { withContent: true }) ? !newHash.startsWith("#") ? `#${newHash}` : newHash : void 0;
11
+ const { path, query, hash } = router.currentRoute.value;
12
+ if (normalizedHash && hash && normalizedHash === hash) {
13
+ return false;
14
+ }
15
+ if (options?.scrollTo === true) {
16
+ (options?.mode === "push" ? router.push : router.replace)({ path, query, hash: normalizedHash });
17
+ return true;
18
+ }
19
+ const newRoute = router.resolve({ path, query, hash: normalizedHash });
20
+ router.currentRoute.value = newRoute;
21
+ window.history[options?.mode === "push" ? "pushState" : "replaceState"](null, "", normalizedHash);
22
+ return true;
23
+ };
24
+ return { value, update };
25
+ }
@@ -1 +1 @@
1
- @layer base{:root{--p-scrollbar-width:0px}html:has(body.p-overflow-hidden){scrollbar-color:transparent var(--color-global-background)}body{background-color:var(--color-global-background);color:var(--color-global-foreground);min-height:100vh;transition:color,background-color;transition-duration:var(--default-transition-duration);@variant dark{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}}@property --background-grid-line-color{syntax:"<color>";inherits:false;initial-value:transparent}#app-root{min-height:100vh;@variant sm{background-position:top;background-size:160px 80px;transition:--background-grid-line-color;transition-duration:var(--default-transition-duration);--background-grid-line-color:var(--color-global-background-accent);background-image:linear-gradient(to bottom,transparent 0 45px,var(--background-grid-line-color) 45px 46px,transparent 46px 59px,var(--background-grid-line-color) 59px 60px,transparent 60px),linear-gradient(to right,transparent 0 80px,var(--background-grid-line-color) 80px 81px,transparent 81px)}}.app-main{min-height:100vh}.app-footer{position:sticky;top:100vh}}
1
+ @layer base{:root{--p-scrollbar-width:0px}html{scroll-behavior:smooth}@media screen and (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}html:has(body.p-overflow-hidden){scrollbar-color:transparent var(--color-global-background)}body{background-color:var(--color-global-background);color:var(--color-global-foreground);min-height:100vh;transition:color,background-color;transition-duration:var(--default-transition-duration);@variant dark{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}}@property --background-grid-line-color{syntax:"<color>";inherits:false;initial-value:transparent}#app-root{min-height:100vh;@variant sm{background-position:top;background-size:160px 74px;transition:--background-grid-line-color;transition-duration:var(--default-transition-duration);--background-grid-line-color:var(--color-global-background-accent);background-image:linear-gradient(to bottom,transparent 0 45px,var(--background-grid-line-color) 45px 46px,transparent 46px 59px,var(--background-grid-line-color) 59px 60px,transparent 60px),linear-gradient(to right,transparent 0 80px,var(--background-grid-line-color) 80px 81px,transparent 81px)}}.app-main{min-height:100vh}.app-footer{position:sticky;top:100vh}}
@@ -1 +1 @@
1
- @utility prose-layout-container{margin-left:auto;margin-right:auto;max-width:var(--container-3xl);width:100%;&.sm{max-width:var(--container-md)}}@layer components{:root{--typo-h6:clamp(var(--text-base),2.500vw,1.2rem);--typo-h5:clamp(var(--typo-h6),3.000vw,1.44rem);--typo-h4:clamp(var(--typo-h5),3.600vw,1.728rem);--typo-h3:clamp(var(--typo-h4),4.320vw,2.0736rem);--typo-h2:clamp(var(--typo-h3),5.184vw,2.4883rem);--typo-h1:clamp(var(--typo-h2),6.221vw,2.986rem);--typo-h1-hero:clamp(var(--typo-h1),9.331vw,4.479rem);--typo-p-hero:clamp(1.25rem,3.125vw,1.5rem)}.font-variant-small-caps{font-variant:small-caps}.icon-inline{align-items:center;display:inline-flex}.icon-inline:before{content:"​";display:block}.prose-container{@apply prose-layout-container}.prose-container:where(:not(.prose+.prose-container,.prose-container+.prose-container))>:first-child,.prose-container:where(:not(.prose+.prose-container,.prose-container+.prose-container))>:first-child>:first-child,.prose:where(:not(.prose+.prose,.prose-container+.prose))>:first-child,.prose:where(:not(.prose+.prose,.prose-container+.prose))>:first-child>:first-child{margin-block-start:0}.prose-container>:last-child,.prose-container>:last-child>:last-child,.prose>:last-child,.prose>:last-child>:last-child{margin-block-end:0}:where(.h1,.h2,.h3,.h4,.h5,.h6).prose,:where(.prose-container,.prose) :where(h1,h2,h3,h4,h5,h6){margin-block-end:.4lh;margin-block-start:.9lh;text-wrap:pretty}:where(.p,.pre,.table,.ol,.ul,.img,.figure,.blockquote).prose,:where(.prose-container,.prose) :where(p,pre,table,ol,ul,img,figure,blockquote){margin-block-end:1lh;text-wrap:pretty}:where(.prose-container,.prose) hr+*{margin-block-start:0}:where(.prose-container,.prose) :has(+hr){margin-block-end:0}.hr,.prose hr,.prose-container hr{border-color:var(--color-global-background-accent);margin-block-end:1lh;margin-block-start:1lh}.h1,.prose h1,.prose-container h1{color:color-mix(in srgb-linear,var(--custom-accent-color) 40%,currentColor);font-size:var(--typo-h1);letter-spacing:.0025em;line-height:1.125}.h1.hero,.prose h1.hero,.prose-container h1.hero{font-size:var(--typo-h1-hero);line-height:1}.h2,.prose h2,.prose-container h2{font-size:var(--typo-h2);font-weight:var(--font-weight-extralight);letter-spacing:.0108em;line-height:1.1765}.h3,.prose h3,.prose-container h3{font-size:var(--typo-h3);font-weight:var(--font-weight-extralight);letter-spacing:.022em;line-height:1.2}.h4,.prose h4,.prose-container h4{font-size:var(--typo-h4);letter-spacing:.035em;line-height:1.25}.h5,.prose h5,.prose-container h5{font-size:var(--typo-h5);letter-spacing:.0532em;line-height:1.28}.h6,.prose h6,.prose-container h6{font-size:var(--typo-h6);letter-spacing:.0532em;line-height:1.28}.p,.prose p,.prose-container p{font-size:1rem;letter-spacing:.03em;line-height:1.5}.p.hero,.prose p.hero,.prose-container p.hero{font-size:var(--typo-p-hero);line-height:1.3}.note{color:var(--color-foreground-scale-g);font-size:.95rem!important;letter-spacing:.05rem!important;line-height:1.5!important}.code,.pre,.prose code,.prose pre,.prose-container code,.prose-container pre{border-radius:.25rem;color:var(--color-foreground-scale-e);font-family:monospace;font-size:.9rem;font-weight:bolder;outline:dashed 2px var(--color-background-scale-g);outline-offset:-2px;padding:.2rem .25rem;transition:color,outline-color;transition-duration:.15s}.code:hover,.pre:hover,.prose code:hover,.prose pre:hover,.prose-container code:hover,.prose-container pre:hover{color:var(--color-global-foreground)}.pre,.prose pre,.prose-container pre{padding:.5rem .75rem}.prose table,.prose-container table,.table{border-collapse:collapse}.prose table td,.prose table th,.prose-container table td,.prose-container table th,.table td,.table th{border:1px solid var(--color-background-scale-f);padding:.5rem;vertical-align:top}.prose table tr:nth-child(2n),.prose-container table tr:nth-child(2n),.table tr:nth-child(2n){background-color:var(--color-background-scale-a)}.prose table th,.prose-container table th,.table th{background-color:var(--color-background-scale-c);font-weight:var(--font-weight-normal);letter-spacing:.1em;text-align:start}.prose table td>:last-child,.prose-container table td>:last-child,.table td>:last-child{margin-block-end:0}.ol,.prose ol,.prose ul,.prose-container ol,.prose-container ul,.ul{list-style-type:disc;padding-inline-start:1.25rem}.ol li ol,.ol li ul,.prose ol li ol,.prose ol li ul,.prose ul li ol,.prose ul li ul,.prose-container ol li ol,.prose-container ol li ul,.prose-container ul li ol,.prose-container ul li ul,.ul li ol,.ul li ul{padding-inline-start:2rem}.ol li:not(:last-child) ol:not(p+ol),.ol li:not(:last-child) ul:not(p+ul),.prose ol li:not(:last-child) ol:not(p+ol),.prose ol li:not(:last-child) ul:not(p+ul),.prose ul li:not(:last-child) ol:not(p+ol),.prose ul li:not(:last-child) ul:not(p+ul),.prose-container ol li:not(:last-child) ol:not(p+ol),.prose-container ol li:not(:last-child) ul:not(p+ul),.prose-container ul li:not(:last-child) ol:not(p+ol),.prose-container ul li:not(:last-child) ul:not(p+ul),.ul li:not(:last-child) ol:not(p+ol),.ul li:not(:last-child) ul:not(p+ul){margin-block-end:0}.ol,.prose ol,.prose-container ol{counter-reset:item;list-style-type:none}.ol>li,.prose ol>li,.prose-container ol>li{counter-increment:item}.ol>li::marker,.prose ol>li::marker,.prose-container ol>li::marker{content:counters(item,".") ". "}.img,.prose img,.prose-container img{border:2px solid var(--color-background-scale-e);border-radius:.25rem;margin-left:auto;margin-right:auto;max-height:450px;width:auto}.figure,.prose figure,.prose-container figure{display:table;margin-left:auto;margin-right:auto}.figure img,.prose figure img,.prose-container figure img{display:block;margin:0}.figure img:has(+figcaption),.prose figure img:has(+figcaption),.prose-container figure img:has(+figcaption){border-bottom-left-radius:0;border-bottom-right-radius:0}.figure figcaption,.prose figure figcaption,.prose-container figure figcaption{background-color:var(--color-background-scale-e);border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;caption-side:bottom;display:table-caption;font-size:.85rem;padding:.5rem;text-align:center}.figure figcaption>*,.prose figure figcaption>*,.prose-container figure figcaption>*{font-size:.85rem}.figure figcaption>:last-child,.prose figure figcaption>:last-child,.prose-container figure figcaption>:last-child{margin-block-end:0}.blockquote,.prose blockquote,.prose-container blockquote{background-color:var(--color-background-scale-b);border-radius:.25rem;font-family:serif;font-size:1.1rem;padding:.25rem .75rem}.prose-numbering-2,.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6{counter-reset:l1}:where(.prose-numbering-2,.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h2{counter-reset:l2}:where(.prose-numbering-2,.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h2:before{content:counter(l1) ". ";counter-increment:l1}:where(.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h3{counter-reset:l3}:where(.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h3:before{content:counter(l1) "." counter(l2) ". ";counter-increment:l2}:where(.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h4{counter-reset:l4}:where(.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h4:before{content:counter(l1) "." counter(l2) "." counter(l3) ". ";counter-increment:l3}:where(.prose-numbering-5,.prose-numbering-6) h5{counter-reset:l5}:where(.prose-numbering-5,.prose-numbering-6) h5:before{content:counter(l1) "." counter(l2) "." counter(l3) "." counter(l4) ". ";counter-increment:l4}.prose-numbering-6 h6{counter-reset:l6}.prose-numbering-6 h6:before{content:counter(l1) "." counter(l2) "." counter(l3) "." counter(l4) "." counter(l5) ". ";counter-increment:l5}}
1
+ @utility prose-layout-container{margin-left:auto;margin-right:auto;max-width:var(--container-3xl);width:100%;&.sm{max-width:var(--container-md)}}@layer components{:root{--typo-h6:clamp(var(--text-base),2.500vw,1.2rem);--typo-h5:clamp(var(--typo-h6),3.000vw,1.44rem);--typo-h4:clamp(var(--typo-h5),3.600vw,1.728rem);--typo-h3:clamp(var(--typo-h4),4.320vw,2.0736rem);--typo-h2:clamp(var(--typo-h3),5.184vw,2.4883rem);--typo-h1:clamp(var(--typo-h2),6.221vw,2.986rem);--typo-h1-hero:clamp(var(--typo-h1),9.331vw,4.479rem);--typo-p-hero:clamp(1.25rem,3.125vw,1.5rem);--extra-scroll-margin:0px}.font-variant-small-caps{font-variant:small-caps}.icon-inline{align-items:center;display:inline-flex}.icon-inline:before{content:"​";display:block}.prose-container{@apply prose-layout-container}.prose-container:where(:not(.prose+.prose-container,.prose-container+.prose-container))>:first-child,.prose-container:where(:not(.prose+.prose-container,.prose-container+.prose-container))>:first-child>:first-child,.prose:where(:not(.prose+.prose,.prose-container+.prose))>:first-child,.prose:where(:not(.prose+.prose,.prose-container+.prose))>:first-child>:first-child{margin-block-start:0}.prose-container>:last-child,.prose-container>:last-child>:last-child,.prose>:last-child,.prose>:last-child>:last-child{margin-block-end:0}:where(.h1,.h2,.h3,.h4,.h5,.h6).prose,:where(.prose-container,.prose) :where(h1,h2,h3,h4,h5,h6){margin-block-end:.4lh;margin-block-start:.9lh;scroll-margin-block-start:calc(--spacing(6) + var(--extra-scroll-margin, 0px));text-wrap:pretty}:where(.p,.pre,.table,.ol,.ul,.img,.figure,.blockquote).prose,:where(.prose-container,.prose) :where(p,pre,table,ol,ul,img,figure,blockquote){margin-block-end:1lh;text-wrap:pretty}:where(.prose-container,.prose) hr+*{margin-block-start:0}:where(.prose-container,.prose) :has(+hr){margin-block-end:0}.hr,.prose hr,.prose-container hr{border-color:var(--color-global-background-accent);margin-block-end:1lh;margin-block-start:1lh}.h1,.prose h1,.prose-container h1{color:color-mix(in srgb-linear,var(--custom-accent-color) 40%,currentColor);font-size:var(--typo-h1);letter-spacing:.0025em;line-height:1.125}.h1.hero,.prose h1.hero,.prose-container h1.hero{font-size:var(--typo-h1-hero);line-height:1}.h2,.prose h2,.prose-container h2{font-size:var(--typo-h2);font-weight:var(--font-weight-extralight);letter-spacing:.0108em;line-height:1.1765}.h3,.prose h3,.prose-container h3{font-size:var(--typo-h3);font-weight:var(--font-weight-extralight);letter-spacing:.022em;line-height:1.2}.h4,.prose h4,.prose-container h4{font-size:var(--typo-h4);letter-spacing:.035em;line-height:1.25}.h5,.prose h5,.prose-container h5{font-size:var(--typo-h5);letter-spacing:.0532em;line-height:1.28}.h6,.prose h6,.prose-container h6{font-size:var(--typo-h6);letter-spacing:.0532em;line-height:1.28}.p,.prose p,.prose-container p{font-size:1rem;letter-spacing:.03em;line-height:1.5}.p.hero,.prose p.hero,.prose-container p.hero{font-size:var(--typo-p-hero);line-height:1.3}.note{color:var(--color-foreground-scale-g);font-size:.95rem!important;letter-spacing:.05rem!important;line-height:1.5!important}.code,.pre,.prose code,.prose pre,.prose-container code,.prose-container pre{border-radius:.25rem;color:var(--color-foreground-scale-e);font-family:monospace;font-size:.9rem;font-weight:bolder;outline:dashed 2px var(--color-background-scale-g);outline-offset:-2px;padding:.2rem .25rem;transition:color,outline-color;transition-duration:.15s}.code:hover,.pre:hover,.prose code:hover,.prose pre:hover,.prose-container code:hover,.prose-container pre:hover{color:var(--color-global-foreground)}.pre,.prose pre,.prose-container pre{padding:.5rem .75rem}.prose table,.prose-container table,.table{border-collapse:collapse}.prose table td,.prose table th,.prose-container table td,.prose-container table th,.table td,.table th{border:1px solid var(--color-background-scale-f);padding:.5rem;vertical-align:top}.prose table tr:nth-child(2n),.prose-container table tr:nth-child(2n),.table tr:nth-child(2n){background-color:var(--color-background-scale-a)}.prose table th,.prose-container table th,.table th{background-color:var(--color-background-scale-c);font-weight:var(--font-weight-normal);letter-spacing:.1em;text-align:start}.prose table td>:last-child,.prose-container table td>:last-child,.table td>:last-child{margin-block-end:0}.ol,.prose ol,.prose ul,.prose-container ol,.prose-container ul,.ul{list-style-type:disc;padding-inline-start:1.25rem}.ol li ol,.ol li ul,.prose ol li ol,.prose ol li ul,.prose ul li ol,.prose ul li ul,.prose-container ol li ol,.prose-container ol li ul,.prose-container ul li ol,.prose-container ul li ul,.ul li ol,.ul li ul{padding-inline-start:2rem}.ol li:not(:last-child) ol:not(p+ol),.ol li:not(:last-child) ul:not(p+ul),.prose ol li:not(:last-child) ol:not(p+ol),.prose ol li:not(:last-child) ul:not(p+ul),.prose ul li:not(:last-child) ol:not(p+ol),.prose ul li:not(:last-child) ul:not(p+ul),.prose-container ol li:not(:last-child) ol:not(p+ol),.prose-container ol li:not(:last-child) ul:not(p+ul),.prose-container ul li:not(:last-child) ol:not(p+ol),.prose-container ul li:not(:last-child) ul:not(p+ul),.ul li:not(:last-child) ol:not(p+ol),.ul li:not(:last-child) ul:not(p+ul){margin-block-end:0}.ol,.prose ol,.prose-container ol{counter-reset:item;list-style-type:none}.ol>li,.prose ol>li,.prose-container ol>li{counter-increment:item}.ol>li::marker,.prose ol>li::marker,.prose-container ol>li::marker{content:counters(item,".") ". "}.img,.prose img,.prose-container img{border:2px solid var(--color-background-scale-e);border-radius:.25rem;margin-left:auto;margin-right:auto;max-height:450px;width:auto}.figure,.prose figure,.prose-container figure{display:table;margin-left:auto;margin-right:auto}.figure img,.prose figure img,.prose-container figure img{display:block;margin:0}.figure img:has(+figcaption),.prose figure img:has(+figcaption),.prose-container figure img:has(+figcaption){border-bottom-left-radius:0;border-bottom-right-radius:0}.figure figcaption,.prose figure figcaption,.prose-container figure figcaption{background-color:var(--color-background-scale-e);border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;caption-side:bottom;display:table-caption;font-size:.85rem;padding:.5rem;text-align:center}.figure figcaption>*,.prose figure figcaption>*,.prose-container figure figcaption>*{font-size:.85rem}.figure figcaption>:last-child,.prose figure figcaption>:last-child,.prose-container figure figcaption>:last-child{margin-block-end:0}.blockquote,.prose blockquote,.prose-container blockquote{background-color:var(--color-background-scale-b);border-radius:.25rem;font-family:serif;font-size:1.1rem;padding:.25rem .75rem}.prose-numbering-2,.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6{counter-reset:l1}:where(.prose-numbering-2,.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h2{counter-reset:l2}:where(.prose-numbering-2,.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h2:before{content:counter(l1) ". ";counter-increment:l1}:where(.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h3{counter-reset:l3}:where(.prose-numbering-3,.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h3:before{content:counter(l1) "." counter(l2) ". ";counter-increment:l2}:where(.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h4{counter-reset:l4}:where(.prose-numbering-4,.prose-numbering-5,.prose-numbering-6) h4:before{content:counter(l1) "." counter(l2) "." counter(l3) ". ";counter-increment:l3}:where(.prose-numbering-5,.prose-numbering-6) h5{counter-reset:l5}:where(.prose-numbering-5,.prose-numbering-6) h5:before{content:counter(l1) "." counter(l2) "." counter(l3) "." counter(l4) ". ";counter-increment:l4}.prose-numbering-6 h6{counter-reset:l6}.prose-numbering-6 h6:before{content:counter(l1) "." counter(l2) "." counter(l3) "." counter(l4) "." counter(l5) ". ";counter-increment:l5}}
@@ -40,3 +40,9 @@ export type StatusLevel = 'info' | 'help' | 'success' | 'warn' | 'error';
40
40
  * separately.
41
41
  */
42
42
  export type StyleStatusLevel = 'default' | 'inverted' | StatusLevel;
43
+ /**
44
+ * CSS classnames that apply pre-configured gradients over their target
45
+ * element. As the type's name suggest, these are intended to be used
46
+ * with images.
47
+ */
48
+ export type ImageMaskPreset = 'image-mask-washout' | 'image-mask-gradient-washout' | 'image-mask-gradient-washout-lite' | 'image-mask-gradient-opacity' | 'image-mask-hero';
@@ -0,0 +1,14 @@
1
+ import type { RouteLocationGeneric } from 'vue-router';
2
+ /**
3
+ * Strictly compare the entirety of two URLs, including their hashes.
4
+ *
5
+ * This is required for two reasons:
6
+ *
7
+ * 1) NuxtLink does not provide equivalent results when parsing `:to` and `:href`
8
+ * props (the value of a URL's `hash` will appear in the `fullPath` of the former,
9
+ * but not the latter).
10
+ * 2) NuxtLink does not take into account the value of `hash` when computing whether
11
+ * a link is active. This makes sense for a lot of circumstances, but in some cases
12
+ * is required.
13
+ */
14
+ export declare function areRoutesStrictEqual(routeA: RouteLocationGeneric | undefined, routeB: RouteLocationGeneric | undefined): boolean;
@@ -0,0 +1,14 @@
1
+ export function areRoutesStrictEqual(routeA, routeB) {
2
+ if (!(routeA && routeB)) {
3
+ return false;
4
+ }
5
+ let fullPathA = routeA.fullPath;
6
+ let fullPathB = routeB.fullPath;
7
+ if (routeA.hash && !fullPathA.endsWith(routeA.hash)) {
8
+ fullPathA += routeA.hash;
9
+ }
10
+ if (routeB.hash && !fullPathB.endsWith(routeB.hash)) {
11
+ fullPathB += routeB.hash;
12
+ }
13
+ return fullPathA === fullPathB;
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resee-movies/nuxt-ux",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "The next-gen user experience library for ReSee Movies - currently in development. ",
5
5
  "repository": {
6
6
  "url": "https://github.com/ReSee-Movies/nuxt-ux.git"
@@ -35,7 +35,7 @@
35
35
  "dist"
36
36
  ],
37
37
  "scripts": {
38
- "dev": "npm run dev:prepare && nuxi dev playground --local --port 3003",
38
+ "dev": "npm run dev:prepare && nuxi dev playground --port 3003 --public",
39
39
  "dev:preview": "npm run dev:build && nuxi preview playground --port 3003",
40
40
  "dev:build": "nuxi build playground",
41
41
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
@@ -72,19 +72,19 @@
72
72
  "dependencies": {
73
73
  "@egoist/tailwindcss-icons": "^1.9.0",
74
74
  "@iconify-json/ph": "^1.2.2",
75
- "@iconify-json/simple-icons": "^1.2.61",
75
+ "@iconify-json/simple-icons": "^1.2.65",
76
76
  "@iconify-json/solar": "^1.2.5",
77
77
  "@nuxt/fonts": "^0.12.1",
78
78
  "@nuxtjs/device": "^4.0.0",
79
79
  "@primeuix/utils": "^0.6.1",
80
- "@primevue/forms": "^4.5.1",
81
- "@primevue/nuxt-module": "^4.5.1",
80
+ "@primevue/forms": "^4.5.4",
81
+ "@primevue/nuxt-module": "^4.5.4",
82
82
  "@resee-movies/utilities": "^0.11.0",
83
- "@tailwindcss/postcss": "^4.1.17",
84
- "@tailwindcss/vite": "^4.1.17",
83
+ "@tailwindcss/postcss": "^4.1.18",
84
+ "@tailwindcss/vite": "^4.1.18",
85
85
  "@vueuse/core": "^14.1.0",
86
- "primevue": "^4.5.1",
87
- "tailwindcss": "^4.1.17",
88
- "zod": "^4.1.13"
86
+ "primevue": "^4.5.4",
87
+ "tailwindcss": "^4.1.18",
88
+ "zod": "^4.3.5"
89
89
  }
90
90
  }