@timmbr/ui 1.11.1 → 1.13.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.
@@ -1 +1 @@
1
- {"version":3,"file":"Inline.d.ts","sourceRoot":"","sources":["../../../src/components/Inline/Inline.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,eAAO,MAAM,MAAM,oFAoDlB,CAAC"}
1
+ {"version":3,"file":"Inline.d.ts","sourceRoot":"","sources":["../../../src/components/Inline/Inline.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,eAAO,MAAM,MAAM,oFAqDlB,CAAC"}
@@ -17,11 +17,12 @@ const Inline = React.forwardRef(
17
17
  justify = "start",
18
18
  wrap = true,
19
19
  divider,
20
+ as,
20
21
  asChild = false,
21
22
  children,
22
23
  ...props
23
24
  }, ref) => {
24
- const Component = asChild ? Slot : "div";
25
+ const Component = asChild ? Slot : as ?? "div";
25
26
  const gapClass = formatGap(gap);
26
27
  const renderChildren = () => {
27
28
  if (!divider) return children;
@@ -14,6 +14,11 @@ export interface InlineProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
14
14
  * Optional divider element rendered between each inline child.
15
15
  */
16
16
  divider?: React.ReactNode;
17
+ /**
18
+ * Renders as a different HTML element or component while keeping Inline styles.
19
+ * e.g. `as="nav"`, `as="footer"`. Ignored when `asChild` is true.
20
+ */
21
+ as?: React.ElementType;
17
22
  /**
18
23
  * If true, renders child element via Radix Slot.
19
24
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Inline.types.d.ts","sourceRoot":"","sources":["../../../src/components/Inline/Inline.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,EACvD,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC;IAC7B;;OAEG;IACH,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
1
+ {"version":3,"file":"Inline.types.d.ts","sourceRoot":"","sources":["../../../src/components/Inline/Inline.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,EACvD,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC;IAC7B;;OAEG;IACH,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;OAGG;IACH,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { ScrollRailProps } from './ScrollRail.types';
3
+ export declare const ScrollRail: React.ForwardRefExoticComponent<ScrollRailProps & React.RefAttributes<HTMLDivElement>>;
4
+ //# sourceMappingURL=ScrollRail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollRail.d.ts","sourceRoot":"","sources":["../../../src/components/ScrollRail/ScrollRail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI1D,eAAO,MAAM,UAAU,wFA+GtB,CAAC"}
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { ChevronLeft, ChevronRight } from '@timmbr/icons';
5
+ import { cn } from '@timmbr/utils';
6
+ import { tapGestures, hoverGestures, Presence, motion, fadeVariants } from '@timmbr/motion';
7
+ import { scrollRailVariants, scrollRailChevronVariants, scrollRailWrapperVariants } from './ScrollRail.styles.js';
8
+ import { useGlobalAnimation } from '../../providers/AnimationProvider.js';
9
+
10
+ const SCROLL_THRESHOLD = 4;
11
+ const ScrollRail = React.forwardRef(
12
+ ({
13
+ gap,
14
+ scrollAmount,
15
+ hideChevrons = false,
16
+ labelPrev = "Scroll left",
17
+ labelNext = "Scroll right",
18
+ className,
19
+ children,
20
+ ...props
21
+ }, ref) => {
22
+ const globalMotion = useGlobalAnimation();
23
+ const trackRef = React.useRef(null);
24
+ const [canScrollLeft, setCanScrollLeft] = React.useState(false);
25
+ const [canScrollRight, setCanScrollRight] = React.useState(false);
26
+ const updateScrollState = React.useCallback(() => {
27
+ const t = trackRef.current;
28
+ if (!t) return;
29
+ setCanScrollLeft(t.scrollLeft > SCROLL_THRESHOLD);
30
+ setCanScrollRight(t.scrollLeft + t.clientWidth < t.scrollWidth - SCROLL_THRESHOLD);
31
+ }, []);
32
+ React.useLayoutEffect(() => {
33
+ updateScrollState();
34
+ }, [updateScrollState]);
35
+ React.useEffect(() => {
36
+ const t = trackRef.current;
37
+ if (!t || typeof ResizeObserver === "undefined") return;
38
+ const ro = new ResizeObserver(updateScrollState);
39
+ ro.observe(t);
40
+ return () => ro.disconnect();
41
+ }, [updateScrollState]);
42
+ const getScrollAmount = () => scrollAmount ?? (trackRef.current?.clientWidth ?? 320) * 0.8;
43
+ const gestureProps = globalMotion ? { whileHover: hoverGestures.scale, whileTap: tapGestures.compress } : {};
44
+ return /* @__PURE__ */ jsxs(
45
+ "div",
46
+ {
47
+ ref,
48
+ "data-slot": "scroll-rail",
49
+ className: cn(scrollRailWrapperVariants(), className),
50
+ ...props,
51
+ children: [
52
+ /* @__PURE__ */ jsx(
53
+ "div",
54
+ {
55
+ ref: trackRef,
56
+ "data-slot": "scroll-rail-track",
57
+ className: scrollRailVariants({ gap }),
58
+ onScroll: updateScrollState,
59
+ children
60
+ }
61
+ ),
62
+ !hideChevrons && /* @__PURE__ */ jsx(Presence, { initial: false, children: canScrollLeft && /* @__PURE__ */ jsx(
63
+ motion.button,
64
+ {
65
+ type: "button",
66
+ "aria-label": labelPrev,
67
+ "data-slot": "scroll-rail-prev",
68
+ className: scrollRailChevronVariants({ side: "left" }),
69
+ initial: "hidden",
70
+ animate: "visible",
71
+ exit: "exit",
72
+ variants: fadeVariants,
73
+ onClick: () => trackRef.current?.scrollBy({ left: -getScrollAmount(), behavior: "smooth" }),
74
+ ...gestureProps,
75
+ children: /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true", className: "size-5" })
76
+ },
77
+ "scroll-rail-prev"
78
+ ) }),
79
+ !hideChevrons && /* @__PURE__ */ jsx(Presence, { initial: false, children: canScrollRight && /* @__PURE__ */ jsx(
80
+ motion.button,
81
+ {
82
+ type: "button",
83
+ "aria-label": labelNext,
84
+ "data-slot": "scroll-rail-next",
85
+ className: scrollRailChevronVariants({ side: "right" }),
86
+ initial: "hidden",
87
+ animate: "visible",
88
+ exit: "exit",
89
+ variants: fadeVariants,
90
+ onClick: () => trackRef.current?.scrollBy({ left: getScrollAmount(), behavior: "smooth" }),
91
+ ...gestureProps,
92
+ children: /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true", className: "size-5" })
93
+ },
94
+ "scroll-rail-next"
95
+ ) })
96
+ ]
97
+ }
98
+ );
99
+ }
100
+ );
101
+ ScrollRail.displayName = "ScrollRail";
102
+
103
+ export { ScrollRail };
@@ -0,0 +1,10 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ export declare const scrollRailWrapperVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
3
+ export declare const scrollRailVariants: (props?: ({
4
+ gap?: "sm" | "md" | "lg" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export declare const scrollRailChevronVariants: (props?: ({
7
+ side?: "left" | "right" | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ export type ScrollRailVariants = VariantProps<typeof scrollRailVariants>;
10
+ //# sourceMappingURL=ScrollRail.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollRail.styles.d.ts","sourceRoot":"","sources":["../../../src/components/ScrollRail/ScrollRail.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,yBAAyB,oFAAyB,CAAC;AAEhE,eAAO,MAAM,kBAAkB;;8EAc9B,CAAC;AAEF,eAAO,MAAM,yBAAyB;;8EAUrC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { cva } from 'class-variance-authority';
2
+
3
+ const scrollRailWrapperVariants = cva("relative w-full");
4
+ const scrollRailVariants = cva(
5
+ "w-full overflow-x-auto pb-4 pt-1 px-1 flex snap-x snap-mandatory scroll-smooth focus:outline-none [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
6
+ {
7
+ variants: {
8
+ gap: {
9
+ sm: "gap-3",
10
+ md: "gap-5 sm:gap-6",
11
+ lg: "gap-6 sm:gap-8"
12
+ }
13
+ },
14
+ defaultVariants: {
15
+ gap: "md"
16
+ }
17
+ }
18
+ );
19
+ const scrollRailChevronVariants = cva(
20
+ "absolute top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full bg-grey-50/70 text-grey-950 shadow-sm backdrop-blur-sm transition-colors hover:bg-grey-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring md:flex",
21
+ {
22
+ variants: {
23
+ side: {
24
+ left: "left-2",
25
+ right: "right-2"
26
+ }
27
+ }
28
+ }
29
+ );
30
+
31
+ export { scrollRailChevronVariants, scrollRailVariants, scrollRailWrapperVariants };
@@ -0,0 +1,16 @@
1
+ import type * as React from 'react';
2
+ import type { ScrollRailVariants } from './ScrollRail.styles';
3
+ export interface ScrollRailProps extends React.HTMLAttributes<HTMLDivElement>, ScrollRailVariants {
4
+ gap?: 'sm' | 'md' | 'lg';
5
+ /** Override px amount scrolled per chevron click. Default: 80% of track clientWidth. */
6
+ scrollAmount?: number;
7
+ /** Suppress chevrons entirely (touch-only contexts). */
8
+ hideChevrons?: boolean;
9
+ /** Accessible label for the left button. @default 'Scroll left' */
10
+ labelPrev?: string;
11
+ /** Accessible label for the right button. @default 'Scroll right' */
12
+ labelNext?: string;
13
+ children?: React.ReactNode;
14
+ className?: string;
15
+ }
16
+ //# sourceMappingURL=ScrollRail.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollRail.types.d.ts","sourceRoot":"","sources":["../../../src/components/ScrollRail/ScrollRail.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,WAAW,eACf,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAC1C,kBAAkB;IACpB,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACzB,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,4 @@
1
+ export * from './ScrollRail';
2
+ export * from './ScrollRail.styles';
3
+ export * from './ScrollRail.types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ScrollRail/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAqBhD,eAAO,MAAM,KAAK,mFA4CjB,CAAC"}
1
+ {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAqBhD,eAAO,MAAM,KAAK,mFA6CjB,CAAC"}
@@ -29,11 +29,12 @@ const Stack = React.forwardRef(
29
29
  align = "stretch",
30
30
  justify = "start",
31
31
  divider,
32
+ as,
32
33
  asChild = false,
33
34
  children,
34
35
  ...props
35
36
  }, ref) => {
36
- const Component = asChild ? Slot : "div";
37
+ const Component = asChild ? Slot : as ?? "div";
37
38
  const gapClass = formatGap(gap);
38
39
  const renderChildren = () => {
39
40
  if (!divider) return children;
@@ -22,6 +22,11 @@ export interface StackProps extends Omit<React.HTMLAttributes<HTMLDivElement>, '
22
22
  * Optional divider element rendered between each child in the stack.
23
23
  */
24
24
  divider?: React.ReactNode;
25
+ /**
26
+ * Renders as a different HTML element or component while keeping Stack styles.
27
+ * e.g. `as="article"`, `as="section"`, `as="header"`. Ignored when `asChild` is true.
28
+ */
29
+ as?: React.ElementType;
25
30
  /**
26
31
  * If true, renders child element via Radix Slot.
27
32
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Stack.types.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACxB,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACtB,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACtB,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,EACvD,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC;IAC5B;;OAEG;IACH,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,mBAAmB,CAAC;IACnD;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
1
+ {"version":3,"file":"Stack.types.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACxB,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACtB,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACtB,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,EACvD,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC;IAC5B;;OAEG;IACH,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,mBAAmB,CAAC;IACnD;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;OAGG;IACH,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ export declare function ZoneProgress(): React.JSX.Element;
3
+ export declare namespace ZoneProgress {
4
+ var displayName: string;
5
+ }
6
+ //# sourceMappingURL=ZoneProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZoneProgress.d.ts","sourceRoot":"","sources":["../../../src/components/ZoneProgress/ZoneProgress.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA0B/B,wBAAgB,YAAY,sBA2F3B;yBA3Fe,YAAY"}
@@ -0,0 +1,96 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { usePathname } from 'next/navigation';
5
+ import { PageProgress } from '../PageProgress/PageProgress.js';
6
+
7
+ function trickle(p) {
8
+ if (p < 20) return p + 5;
9
+ if (p < 50) return p + 3;
10
+ if (p < 70) return p + 2;
11
+ if (p < 85) return p + 1;
12
+ return p;
13
+ }
14
+ function ZoneProgress() {
15
+ const pathname = usePathname();
16
+ const [loading, setLoading] = React.useState(false);
17
+ const [progress, setProgress] = React.useState(void 0);
18
+ const tickRef = React.useRef(null);
19
+ const committedPathnameRef = React.useRef(pathname);
20
+ React.useLayoutEffect(() => {
21
+ committedPathnameRef.current = pathname;
22
+ });
23
+ const startProgress = React.useCallback(() => {
24
+ if (tickRef.current) clearInterval(tickRef.current);
25
+ setLoading(true);
26
+ setProgress(5);
27
+ tickRef.current = setInterval(() => {
28
+ setProgress((p) => p !== void 0 ? trickle(p) : p);
29
+ }, 200);
30
+ }, []);
31
+ const finishProgress = React.useCallback(() => {
32
+ if (tickRef.current) {
33
+ clearInterval(tickRef.current);
34
+ tickRef.current = null;
35
+ }
36
+ setProgress(100);
37
+ setTimeout(() => {
38
+ setLoading(false);
39
+ setProgress(void 0);
40
+ }, 400);
41
+ }, []);
42
+ React.useEffect(() => {
43
+ const handleClick = (e) => {
44
+ const anchor = e.target.closest("a");
45
+ if (!(anchor instanceof HTMLAnchorElement)) return;
46
+ if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
47
+ if (anchor.target === "_blank") return;
48
+ const href = anchor.getAttribute("href");
49
+ if (!href || href.startsWith("#") || href.startsWith("javascript:")) return;
50
+ try {
51
+ const url = new URL(href, location.origin);
52
+ if (url.origin !== location.origin) return;
53
+ if (url.pathname + url.search === location.pathname + location.search) return;
54
+ } catch {
55
+ return;
56
+ }
57
+ startProgress();
58
+ };
59
+ const handlePopState = () => {
60
+ if (location.pathname !== committedPathnameRef.current) {
61
+ startProgress();
62
+ }
63
+ };
64
+ document.addEventListener("click", handleClick);
65
+ window.addEventListener("popstate", handlePopState);
66
+ return () => {
67
+ document.removeEventListener("click", handleClick);
68
+ window.removeEventListener("popstate", handlePopState);
69
+ if (tickRef.current) clearInterval(tickRef.current);
70
+ };
71
+ }, [startProgress]);
72
+ React.useEffect(() => {
73
+ if (loading) finishProgress();
74
+ }, [pathname, finishProgress]);
75
+ React.useEffect(() => {
76
+ const onHover = (e) => {
77
+ const a = e.target.closest('a[data-cross-zone="true"]');
78
+ if (!(a instanceof HTMLAnchorElement)) return;
79
+ const { href } = a;
80
+ if (!href) return;
81
+ const escaped = href.replace(/"/g, '\\"');
82
+ if (!document.querySelector(`link[rel="prefetch"][href="${escaped}"]`)) {
83
+ const el = document.createElement("link");
84
+ el.rel = "prefetch";
85
+ el.href = href;
86
+ document.head.appendChild(el);
87
+ }
88
+ };
89
+ document.addEventListener("mouseover", onHover);
90
+ return () => document.removeEventListener("mouseover", onHover);
91
+ }, []);
92
+ return /* @__PURE__ */ jsx(PageProgress, { loading, progress });
93
+ }
94
+ ZoneProgress.displayName = "ZoneProgress";
95
+
96
+ export { ZoneProgress };
@@ -0,0 +1,2 @@
1
+ export { ZoneProgress } from './ZoneProgress';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ZoneProgress/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export * from './components/Grid';
6
6
  export * from './components/Center';
7
7
  export * from './components/Stack';
8
8
  export * from './components/Inline';
9
+ export * from './components/ScrollRail';
9
10
  export * from './components/Input';
10
11
  export * from './components/Textarea';
11
12
  export * from './components/Select';
@@ -49,6 +50,7 @@ export * from './components/Text';
49
50
  export * from './components/Alert';
50
51
  export * from './components/Progress';
51
52
  export * from './components/PageProgress';
53
+ export * from './components/ZoneProgress';
52
54
  export * from './components/Spinner';
53
55
  export * from './components/Skeleton';
54
56
  export * from './components/EmptyState';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3D,cAAc,aAAa,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3D,cAAc,aAAa,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -81,6 +81,7 @@ export { RadioCard } from './components/RadioCard/RadioCard.js';
81
81
  export { RangeSlider } from './components/RangeSlider/RangeSlider.js';
82
82
  export { Rating } from './components/Rating/Rating.js';
83
83
  export { SNACKBAR_EXIT_MS, snackbar, snackbarStore } from './components/Snackbar/snackbarStore.js';
84
+ export { ScrollRail } from './components/ScrollRail/ScrollRail.js';
84
85
  export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectSeparator, SelectTrigger, SelectValue } from './components/Select/Select.js';
85
86
  export { SideBarNavigation } from './components/SideBarNavigation/SideBarNavigation.js';
86
87
  export { SidebarBranding } from './components/SideBarNavigation/subcomponents/SidebarBranding.js';
@@ -113,6 +114,7 @@ export { Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastT
113
114
  export { ToastContainer } from './components/Toast/ToastContainer.js';
114
115
  export { Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from './components/Tooltip/Tooltip.js';
115
116
  export { VisuallyHidden } from './components/VisuallyHidden/VisuallyHidden.js';
117
+ export { ZoneProgress } from './components/ZoneProgress/ZoneProgress.js';
116
118
  export { accordionContentVariants, accordionItemVariants, accordionTriggerVariants } from './components/Accordion/Accordion.styles.js';
117
119
  export { alertDialogBodyVariants, alertDialogContentVariants, alertDialogDescriptionVariants, alertDialogFooterVariants, alertDialogHeaderVariants, alertDialogMediaVariants, alertDialogOverlayVariants, alertDialogTitleVariants } from './components/AlertDialog/AlertDialog.styles.js';
118
120
  export { alertIconVariants, alertVariants } from './components/Alert/Alert.styles.js';
@@ -163,6 +165,7 @@ export { radioCardDotClass, radioCardMarkerClass, radioCardVariants } from './co
163
165
  export { radioIndicatorVariants, radioItemVariants } from './components/Radio/Radio.styles.js';
164
166
  export { rangeSliderRangeVariants, rangeSliderRootVariants, rangeSliderThumbVariants, rangeSliderTrackVariants } from './components/RangeSlider/RangeSlider.styles.js';
165
167
  export { ratingVariants } from './components/Rating/Rating.styles.js';
168
+ export { scrollRailChevronVariants, scrollRailVariants, scrollRailWrapperVariants } from './components/ScrollRail/ScrollRail.styles.js';
166
169
  export { selectContentVariants, selectItemVariants, selectTriggerVariants } from './components/Select/Select.styles.js';
167
170
  export { skeletonVariants } from './components/Skeleton/Skeleton.styles.js';
168
171
  export { snackbarActionVariants, snackbarCloseVariants, snackbarHostVariants, snackbarIconVariants, snackbarVariants } from './components/Snackbar/Snackbar.styles.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmbr/ui",
3
- "version": "1.11.1",
3
+ "version": "1.13.0",
4
4
  "description": "High-performance, Next.js App Router-compatible UI design system components for Timmbr",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,8 +44,8 @@
44
44
  "input-otp": "^1.5.0",
45
45
  "@timmbr/icons": "1.6.0",
46
46
  "@timmbr/hooks": "1.1.0",
47
- "@timmbr/utils": "1.6.0",
48
47
  "@timmbr/theme": "1.3.0",
48
+ "@timmbr/utils": "1.6.0",
49
49
  "@timmbr/motion": "1.2.5"
50
50
  },
51
51
  "peerDependencies": {