@devalok/shilp-sutra 0.52.0 → 0.53.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/MIGRATION.md +6 -0
- package/dist/_chunks/motion-provider.js +7 -6
- package/dist/_chunks/motion-provider.js.map +1 -1
- package/dist/_chunks/success.js +53 -53
- package/dist/ai/command-bar.js +158 -158
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js +5 -5
- package/dist/composed/command-palette.js +17 -17
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/priority-indicator.d.ts +15 -6
- package/dist/composed/priority-indicator.d.ts.map +1 -1
- package/dist/composed/priority-indicator.js +37 -88
- package/dist/composed/priority-indicator.js.map +1 -1
- package/dist/composed/schedule-view.d.ts +17 -2
- package/dist/composed/schedule-view.d.ts.map +1 -1
- package/dist/composed/schedule-view.js +163 -64
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/motion/motion-provider.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.d.ts +32 -6
- package/dist/shell/bottom-navbar.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.js +156 -129
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/tokens/primitives.css +6 -2
- package/dist/tokens/utilities.css +6 -0
- package/dist/ui/autocomplete.d.ts +34 -32
- package/dist/ui/autocomplete.d.ts.map +1 -1
- package/dist/ui/autocomplete.js +115 -110
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/combobox.js +4 -4
- package/dist/ui/index.js +30 -30
- package/dist/ui/search-input.js +4 -4
- package/dist/ui/sidebar.js +7 -7
- package/docs/components/composed/priority-indicator.md +22 -11
- package/docs/components/composed/schedule-view.md +20 -5
- package/docs/components/shell/bottom-navbar.md +24 -5
- package/docs/components/ui/autocomplete.md +26 -10
- package/llms.txt +1 -1
- package/mcp-manifest.json +179 -26
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/references/components.md +1 -1
|
@@ -1,29 +1,55 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { IconInput } from '../ui/lib/icon-input';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
+
export interface BottomNavbarUser {
|
|
5
|
+
name: string;
|
|
6
|
+
role?: string;
|
|
7
|
+
}
|
|
4
8
|
export interface BottomNavItem {
|
|
5
9
|
title: string;
|
|
6
10
|
href: string;
|
|
7
11
|
/** Icon for this nav item. Accepts any `IconInput`. */
|
|
8
12
|
icon: IconInput;
|
|
13
|
+
/** Icon shown when the item is active — e.g. a filled variant. Falls back to `icon`. */
|
|
14
|
+
activeIcon?: IconInput;
|
|
9
15
|
/** When true, the route matches only when the path is exactly equal */
|
|
10
16
|
exact?: boolean;
|
|
11
17
|
/** Notification badge count. 0 or undefined = hidden, 1–99 = shown, >99 = "99+" */
|
|
12
18
|
badge?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Roles allowed to see this item, matched against `user.role`. Omit to show
|
|
21
|
+
* it to everyone. For arbitrary logic, use `canView` instead.
|
|
22
|
+
*/
|
|
23
|
+
roles?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Visibility predicate — full control over whether this item renders.
|
|
26
|
+
* Receives the current `user` (or `null`). Takes precedence over `roles`.
|
|
27
|
+
*/
|
|
28
|
+
canView?: (user: BottomNavbarUser | null) => boolean;
|
|
13
29
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Active-item indicator, animated between items on selection:
|
|
32
|
+
* - `pill` (default) — Material-3 tonal pill behind the icon
|
|
33
|
+
* - `underline` — top accent bar (Material-2 tab style)
|
|
34
|
+
* - `tint` — subtle background tint on the whole active cell
|
|
35
|
+
* - `none` — no shape; rely on the filled `activeIcon` + accent color (iOS)
|
|
36
|
+
*/
|
|
37
|
+
export type BottomNavIndicator = 'pill' | 'underline' | 'tint' | 'none';
|
|
38
|
+
/** Show labels always (default) or only for the selected item (narrow viewports). */
|
|
39
|
+
export type BottomNavLabelVisibility = 'always' | 'selected';
|
|
18
40
|
export interface BottomNavbarProps extends React.HTMLAttributes<HTMLElement> {
|
|
19
41
|
/** Currently active pathname */
|
|
20
42
|
currentPath?: string;
|
|
21
|
-
/**
|
|
43
|
+
/** Current user. Drives per-item role gating via `item.roles` / `item.canView`. */
|
|
22
44
|
user?: BottomNavbarUser | null;
|
|
23
45
|
/** Primary nav items shown directly in the bottom bar (max 4 recommended) */
|
|
24
46
|
primaryItems?: BottomNavItem[];
|
|
25
|
-
/** Additional items shown in the "More" overflow
|
|
47
|
+
/** Additional items shown in the "More" overflow sheet */
|
|
26
48
|
moreItems?: BottomNavItem[];
|
|
49
|
+
/** Active-indicator style. @default 'pill' */
|
|
50
|
+
indicator?: BottomNavIndicator;
|
|
51
|
+
/** Label visibility. @default 'always' */
|
|
52
|
+
labelVisibility?: BottomNavLabelVisibility;
|
|
27
53
|
/** Additional className for the nav element */
|
|
28
54
|
className?: string;
|
|
29
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navbar.d.ts","sourceRoot":"","sources":["../../src/shell/bottom-navbar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bottom-navbar.d.ts","sourceRoot":"","sources":["../../src/shell/bottom-navbar.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAWrD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,IAAI,EAAE,SAAS,CAAA;IACf,wFAAwF;IACxF,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,KAAK,OAAO,CAAA;CACrD;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,CAAA;AACvE,qFAAqF;AACrF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,UAAU,CAAA;AAE5D,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC;IAC1E,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,IAAI,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,aAAa,EAAE,CAAA;IAC9B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,aAAa,EAAE,CAAA;IAC3B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,kBAAkB,CAAA;IAC9B,0CAA0C;IAC1C,eAAe,CAAC,EAAE,wBAAwB,CAAA;IAC1C,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAwID,QAAA,MAAM,YAAY,uFA0HjB,CAAA;AAGD,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -4,158 +4,185 @@ import { springs as t } from "../ui/lib/motion.js";
|
|
|
4
4
|
import { cn as n } from "../ui/lib/utils.js";
|
|
5
5
|
import { Icon as r } from "../ui/icon.js";
|
|
6
6
|
import { normalizeIcon as i } from "../_chunks/normalize-icon.js";
|
|
7
|
-
import {
|
|
7
|
+
import { BadgeCompound as a } from "../_chunks/badge-group.js";
|
|
8
|
+
import { Sheet as o, SheetContent as s, SheetHeader as c, SheetTitle as l, SheetTrigger as u } from "../ui/sheet.js";
|
|
9
|
+
import { useLink as d } from "../_chunks/link-context.js";
|
|
8
10
|
import "./link-context.js";
|
|
9
|
-
import * as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { IconDots as
|
|
13
|
-
import {
|
|
11
|
+
import * as f from "react";
|
|
12
|
+
import { useState as p } from "react";
|
|
13
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
14
|
+
import { IconDots as g } from "@tabler/icons-react";
|
|
15
|
+
import { motion as _, useReducedMotion as v } from "framer-motion";
|
|
14
16
|
//#region src/shell/bottom-navbar.tsx
|
|
15
|
-
function y(
|
|
17
|
+
function y(e, t) {
|
|
18
|
+
return e.canView ? e.canView(t) : e.roles && e.roles.length > 0 ? !!t?.role && e.roles.includes(t.role) : !0;
|
|
19
|
+
}
|
|
20
|
+
function b({ count: e }) {
|
|
16
21
|
if (!e || e <= 0) return null;
|
|
17
|
-
let t = e > 99 ? "99+" : String(e)
|
|
18
|
-
return /* @__PURE__ */
|
|
22
|
+
let t = e > 99 ? "99+" : String(e);
|
|
23
|
+
return /* @__PURE__ */ m(a, {
|
|
24
|
+
color: "error",
|
|
25
|
+
variant: "solid",
|
|
26
|
+
size: "xs",
|
|
19
27
|
"aria-label": `${e} notifications`,
|
|
20
|
-
className:
|
|
28
|
+
className: "pointer-events-none absolute -end-1 -top-1 justify-center px-ds-01 tabular-nums motion-safe:animate-in motion-safe:zoom-in-75",
|
|
21
29
|
children: t
|
|
22
30
|
});
|
|
23
31
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
function x({ indicator: e, layoutId: n, reduced: r }) {
|
|
33
|
+
if (e === "none") return null;
|
|
34
|
+
let i = {
|
|
35
|
+
layoutId: n,
|
|
36
|
+
"aria-hidden": !0,
|
|
37
|
+
transition: r ? { duration: 0 } : t.snappy,
|
|
38
|
+
initial: !r && { opacity: 0 },
|
|
39
|
+
animate: { opacity: 1 }
|
|
40
|
+
};
|
|
41
|
+
return e === "underline" ? /* @__PURE__ */ m(_.span, {
|
|
42
|
+
...i,
|
|
43
|
+
className: "absolute top-0 h-[3px] w-full rounded-b-control-inner bg-accent-9"
|
|
44
|
+
}) : e === "tint" ? /* @__PURE__ */ m(_.span, {
|
|
45
|
+
...i,
|
|
46
|
+
className: "absolute inset-0 rounded-control bg-accent-3"
|
|
47
|
+
}) : /* @__PURE__ */ m(_.span, {
|
|
48
|
+
...i,
|
|
49
|
+
className: "absolute inset-0 rounded-pill bg-accent-3"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
var S = "relative flex h-16 w-full min-w-0 cursor-pointer flex-col items-center justify-center gap-ds-02 px-ds-01 pt-0 text-body-sm transition-colors duration-fast-02 ease-productive-standard";
|
|
53
|
+
function C({ item: r, isActive: a, indicator: o, indicatorId: s, showLabel: c, reduced: l }) {
|
|
54
|
+
let u = d();
|
|
55
|
+
return /* @__PURE__ */ m(_.div, {
|
|
27
56
|
whileTap: l ? void 0 : { scale: .96 },
|
|
28
57
|
transition: l ? { duration: 0 } : t.snappy,
|
|
29
|
-
className: "flex
|
|
30
|
-
children: /* @__PURE__ */
|
|
58
|
+
className: "flex min-w-0 flex-1 basis-0",
|
|
59
|
+
children: /* @__PURE__ */ h(u, {
|
|
31
60
|
href: r.href,
|
|
32
|
-
onClick: s,
|
|
33
61
|
"aria-label": r.title,
|
|
34
|
-
"aria-current":
|
|
35
|
-
className: n(
|
|
36
|
-
children: /* @__PURE__ */
|
|
37
|
-
|
|
62
|
+
"aria-current": a ? "page" : void 0,
|
|
63
|
+
className: n(S, a ? "font-semibold text-accent-11" : "text-surface-fg-subtle"),
|
|
64
|
+
children: [a && o === "tint" && /* @__PURE__ */ m(x, {
|
|
65
|
+
indicator: "tint",
|
|
66
|
+
layoutId: s,
|
|
67
|
+
reduced: l
|
|
68
|
+
}), /* @__PURE__ */ h("div", {
|
|
69
|
+
className: "relative flex w-full min-w-0 flex-col items-center gap-ds-02",
|
|
38
70
|
children: [
|
|
39
|
-
o && /* @__PURE__ */
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
transition: l ? { duration: 0 } : t.snappy
|
|
71
|
+
a && o === "underline" && /* @__PURE__ */ m(x, {
|
|
72
|
+
indicator: "underline",
|
|
73
|
+
layoutId: s,
|
|
74
|
+
reduced: l
|
|
44
75
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
46
|
-
className: "relative
|
|
47
|
-
children: [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
76
|
+
/* @__PURE__ */ h("div", {
|
|
77
|
+
className: "relative px-ds-04 py-ds-01",
|
|
78
|
+
children: [
|
|
79
|
+
a && o === "pill" && /* @__PURE__ */ m(x, {
|
|
80
|
+
indicator: "pill",
|
|
81
|
+
layoutId: s,
|
|
82
|
+
reduced: l
|
|
83
|
+
}),
|
|
84
|
+
/* @__PURE__ */ m("span", {
|
|
85
|
+
className: "relative [&>svg]:h-ico-md [&>svg]:w-ico-md",
|
|
86
|
+
"aria-hidden": "true",
|
|
87
|
+
children: /* @__PURE__ */ m(e, {
|
|
88
|
+
size: "md",
|
|
89
|
+
children: i(a && r.activeIcon ? r.activeIcon : r.icon)
|
|
90
|
+
})
|
|
91
|
+
}),
|
|
92
|
+
r.badge != null && /* @__PURE__ */ m(b, { count: r.badge })
|
|
93
|
+
]
|
|
55
94
|
}),
|
|
56
|
-
/* @__PURE__ */
|
|
57
|
-
className: "text-center",
|
|
95
|
+
c && /* @__PURE__ */ m("span", {
|
|
96
|
+
className: "max-w-full truncate text-center",
|
|
58
97
|
children: r.title
|
|
59
98
|
})
|
|
60
99
|
]
|
|
61
|
-
})
|
|
100
|
+
})]
|
|
62
101
|
})
|
|
63
102
|
});
|
|
64
103
|
}
|
|
65
|
-
var
|
|
66
|
-
let
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let M = (e, t = !1) => t || e === "/" ? o === e : o.startsWith(e), N = S.some((e) => M(e.href, e.exact));
|
|
71
|
-
return /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(g, { children: O && /* @__PURE__ */ p("div", {
|
|
72
|
-
className: "fixed inset-0 z-overlay md:hidden",
|
|
73
|
-
onClick: () => k(!1),
|
|
74
|
-
children: [/* @__PURE__ */ f("div", { className: "absolute inset-0 bg-overlay" }), /* @__PURE__ */ p(_.div, {
|
|
75
|
-
ref: A,
|
|
76
|
-
role: "dialog",
|
|
77
|
-
"aria-label": "More navigation",
|
|
78
|
-
initial: { y: "100%" },
|
|
79
|
-
animate: { y: 0 },
|
|
80
|
-
exit: { y: "100%" },
|
|
81
|
-
transition: D ? { duration: 0 } : t.smooth,
|
|
82
|
-
className: "absolute bottom-[72px] left-0 right-0 rounded-t-bubble border-t border-surface-border-strong bg-surface-overlay p-ds-05 pb-ds-03",
|
|
83
|
-
onClick: (e) => e.stopPropagation(),
|
|
84
|
-
onKeyDown: (e) => {
|
|
85
|
-
e.stopPropagation(), e.key === "Escape" && j();
|
|
86
|
-
},
|
|
87
|
-
children: [/* @__PURE__ */ p("div", {
|
|
88
|
-
className: "mb-ds-04 flex items-center justify-between",
|
|
89
|
-
children: [/* @__PURE__ */ f("span", {
|
|
90
|
-
className: "text-body-md font-semibold text-surface-fg",
|
|
91
|
-
children: "More"
|
|
92
|
-
}), /* @__PURE__ */ f("button", {
|
|
93
|
-
onClick: () => k(!1),
|
|
94
|
-
"aria-label": "Close more menu",
|
|
95
|
-
className: "flex h-ds-sm w-ds-sm items-center justify-center rounded-pill hover:bg-surface-raised-hover",
|
|
96
|
-
children: /* @__PURE__ */ f(r, {
|
|
97
|
-
icon: h,
|
|
98
|
-
size: "sm",
|
|
99
|
-
className: "text-surface-fg-muted"
|
|
100
|
-
})
|
|
101
|
-
})]
|
|
102
|
-
}), /* @__PURE__ */ f("div", {
|
|
103
|
-
className: "grid grid-cols-4 gap-ds-03",
|
|
104
|
-
children: S.map((t) => /* @__PURE__ */ p(E, {
|
|
105
|
-
href: t.href,
|
|
106
|
-
onClick: () => k(!1),
|
|
107
|
-
className: n("flex flex-col items-center gap-ds-02b rounded-overlay-lg p-ds-04 text-body-sm transition-colors ease-productive-standard", M(t.href, t.exact) ? "bg-surface-raised-hover text-accent-11" : "text-surface-fg-subtle hover:bg-surface-raised-hover"),
|
|
108
|
-
children: [/* @__PURE__ */ f("span", {
|
|
109
|
-
className: "[&>svg]:h-ico-md [&>svg]:w-ico-md",
|
|
110
|
-
children: /* @__PURE__ */ f(e, {
|
|
111
|
-
size: "md",
|
|
112
|
-
children: i(t.icon)
|
|
113
|
-
})
|
|
114
|
-
}), /* @__PURE__ */ f("span", {
|
|
115
|
-
className: "text-center",
|
|
116
|
-
children: t.title
|
|
117
|
-
})]
|
|
118
|
-
}, t.href))
|
|
119
|
-
})]
|
|
120
|
-
})]
|
|
121
|
-
}) }), /* @__PURE__ */ p("nav", {
|
|
122
|
-
...w,
|
|
123
|
-
ref: T,
|
|
104
|
+
var w = f.forwardRef(({ currentPath: a = "/", user: b = null, primaryItems: w = [], moreItems: T = [], indicator: E = "pill", labelVisibility: D = "always", className: O, ...k }, A) => {
|
|
105
|
+
let j = d(), M = v() ?? !1, [N, P] = p(!1), F = `${f.useId()}-nav-indicator`, I = (e, t = !1) => t || e === "/" ? a === e : a.startsWith(e), L = w.filter((e) => y(e, b)), R = T.filter((e) => y(e, b)), z = R.some((e) => I(e.href, e.exact)), B = N || z, V = D === "always" || B;
|
|
106
|
+
return /* @__PURE__ */ h("nav", {
|
|
107
|
+
...k,
|
|
108
|
+
ref: A,
|
|
124
109
|
"aria-label": "Mobile navigation",
|
|
125
|
-
className: n("fixed bottom-0
|
|
126
|
-
children: [
|
|
110
|
+
className: n("fixed bottom-0 start-0 end-0 z-sticky flex w-full flex-row items-stretch justify-between border-t border-surface-border-strong bg-surface-chrome px-ds-05 pb-safe pt-0 md:hidden", O),
|
|
111
|
+
children: [L.map((e) => /* @__PURE__ */ m(C, {
|
|
127
112
|
item: e,
|
|
128
|
-
isActive:
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
113
|
+
isActive: I(e.href, e.exact),
|
|
114
|
+
indicator: E,
|
|
115
|
+
indicatorId: F,
|
|
116
|
+
showLabel: D === "always" || I(e.href, e.exact),
|
|
117
|
+
reduced: M
|
|
118
|
+
}, e.href)), R.length > 0 && /* @__PURE__ */ h(o, {
|
|
119
|
+
open: N,
|
|
120
|
+
onOpenChange: P,
|
|
121
|
+
children: [/* @__PURE__ */ m(u, {
|
|
122
|
+
asChild: !0,
|
|
123
|
+
children: /* @__PURE__ */ h(_.button, {
|
|
124
|
+
type: "button",
|
|
125
|
+
"aria-label": "More navigation options",
|
|
126
|
+
whileTap: M ? void 0 : { scale: .96 },
|
|
127
|
+
transition: M ? { duration: 0 } : t.snappy,
|
|
128
|
+
className: n(S, "min-w-0 flex-1 basis-0", B ? "font-semibold text-accent-11" : "text-surface-fg-subtle"),
|
|
129
|
+
children: [B && E === "tint" && /* @__PURE__ */ m(x, {
|
|
130
|
+
indicator: "tint",
|
|
131
|
+
layoutId: F,
|
|
132
|
+
reduced: M
|
|
133
|
+
}), /* @__PURE__ */ h("div", {
|
|
134
|
+
className: "relative flex w-full min-w-0 flex-col items-center gap-ds-02",
|
|
135
|
+
children: [
|
|
136
|
+
B && E === "underline" && /* @__PURE__ */ m(x, {
|
|
137
|
+
indicator: "underline",
|
|
138
|
+
layoutId: F,
|
|
139
|
+
reduced: M
|
|
140
|
+
}),
|
|
141
|
+
/* @__PURE__ */ h("div", {
|
|
142
|
+
className: "relative px-ds-04 py-ds-01",
|
|
143
|
+
children: [B && E === "pill" && /* @__PURE__ */ m(x, {
|
|
144
|
+
indicator: "pill",
|
|
145
|
+
layoutId: F,
|
|
146
|
+
reduced: M
|
|
147
|
+
}), /* @__PURE__ */ m(r, { icon: g })]
|
|
148
|
+
}),
|
|
149
|
+
V && /* @__PURE__ */ m("span", {
|
|
150
|
+
className: "max-w-full truncate text-center",
|
|
151
|
+
children: "More"
|
|
152
|
+
})
|
|
153
|
+
]
|
|
154
|
+
})]
|
|
155
|
+
})
|
|
156
|
+
}), /* @__PURE__ */ h(s, {
|
|
157
|
+
side: "bottom",
|
|
158
|
+
className: "rounded-t-bubble",
|
|
159
|
+
children: [/* @__PURE__ */ m(c, { children: /* @__PURE__ */ m(l, { children: "More" }) }), /* @__PURE__ */ m("div", {
|
|
160
|
+
className: "grid grid-cols-[repeat(auto-fit,minmax(72px,1fr))] gap-ds-03 pt-ds-04",
|
|
161
|
+
children: R.map((t) => {
|
|
162
|
+
let r = I(t.href, t.exact);
|
|
163
|
+
return /* @__PURE__ */ h(j, {
|
|
164
|
+
href: t.href,
|
|
165
|
+
onClick: () => P(!1),
|
|
166
|
+
"aria-current": r ? "page" : void 0,
|
|
167
|
+
className: n("flex min-w-0 flex-col items-center gap-ds-02b rounded-overlay-lg p-ds-04 text-body-sm transition-colors ease-productive-standard", r ? "bg-surface-raised-hover text-accent-11" : "text-surface-fg-subtle hover:bg-surface-raised-hover"),
|
|
168
|
+
children: [/* @__PURE__ */ m("span", {
|
|
169
|
+
className: "[&>svg]:h-ico-md [&>svg]:w-ico-md",
|
|
170
|
+
"aria-hidden": "true",
|
|
171
|
+
children: /* @__PURE__ */ m(e, {
|
|
172
|
+
size: "md",
|
|
173
|
+
children: i(t.icon)
|
|
174
|
+
})
|
|
175
|
+
}), /* @__PURE__ */ m("span", {
|
|
176
|
+
className: "max-w-full truncate text-center",
|
|
177
|
+
children: t.title
|
|
178
|
+
})]
|
|
179
|
+
}, t.href);
|
|
153
180
|
})
|
|
154
|
-
]
|
|
155
|
-
})
|
|
181
|
+
})]
|
|
182
|
+
})]
|
|
156
183
|
})]
|
|
157
|
-
})
|
|
184
|
+
});
|
|
158
185
|
});
|
|
159
|
-
|
|
186
|
+
w.displayName = "BottomNavbar";
|
|
160
187
|
//#endregion
|
|
161
|
-
export {
|
|
188
|
+
export { w as BottomNavbar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navbar.js","names":[],"sources":["../../src/shell/bottom-navbar.tsx"],"sourcesContent":["'use client'\n\n/**\n * BottomNavbar -- Mobile bottom navigation bar.\n *\n * Props-driven: accepts currentPath, user, navItems instead of\n * reading from Remix hooks or Zustand stores.\n */\nimport { IconDots, IconX } from '@tabler/icons-react'\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\nimport { useCallback,useEffect, useRef, useState } from 'react'\n\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { useLink } from './link-context'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface BottomNavItem {\n title: string\n href: string\n /** Icon for this nav item. Accepts any `IconInput`. */\n icon: IconInput\n /** When true, the route matches only when the path is exactly equal */\n exact?: boolean\n /** Notification badge count. 0 or undefined = hidden, 1–99 = shown, >99 = \"99+\" */\n badge?: number\n}\n\nexport interface BottomNavbarUser {\n name: string\n role?: string\n}\n\nexport interface BottomNavbarProps\n extends React.HTMLAttributes<HTMLElement> {\n /** Currently active pathname */\n currentPath?: string\n /** User information (used to determine admin status, presence) */\n user?: BottomNavbarUser | null\n /** Primary nav items shown directly in the bottom bar (max 4 recommended) */\n primaryItems?: BottomNavItem[]\n /** Additional items shown in the \"More\" overflow menu */\n moreItems?: BottomNavItem[]\n /** Additional className for the nav element */\n className?: string\n}\n\n// -----------------------------------------------------------------------\n// NavBadge (internal)\n// -----------------------------------------------------------------------\n\nfunction NavBadge({ count }: { count: number }) {\n if (!count || count <= 0) return null\n const display = count > 99 ? '99+' : String(count)\n const isMultiDigit = count >= 10\n return (\n <span\n aria-label={`${count} notifications`}\n className={cn(\n 'absolute -right-1 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-pill bg-error-9 text-[10px] font-semibold leading-none text-error-fg animate-in zoom-in-75',\n isMultiDigit ? 'px-0.5' : '',\n )}\n >\n {display}\n </span>\n )\n}\n\n// -----------------------------------------------------------------------\n// BottomNavLink (internal)\n// -----------------------------------------------------------------------\n\nfunction BottomNavLink({\n item,\n isActive,\n onClick,\n}: {\n item: BottomNavItem\n isActive: boolean\n onClick?: () => void\n}) {\n const Link = useLink()\n const prefersReducedMotion = useReducedMotion()\n return (\n <motion.div whileTap={prefersReducedMotion ? undefined : { scale: 0.96 }} transition={prefersReducedMotion ? { duration: 0 } : springs.snappy} className=\"flex max-w-[70px] flex-1\">\n <Link\n href={item.href}\n onClick={onClick}\n aria-label={item.title}\n aria-current={isActive ? 'page' : undefined}\n className={cn(\n 'flex h-16 w-full cursor-pointer flex-col items-center gap-ds-02 p-ds-02 pt-0 text-body-sm transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'font-semibold text-accent-11'\n : 'text-surface-fg-subtle',\n )}\n >\n <div className=\"relative flex w-full flex-col items-center gap-ds-02\">\n {isActive && (\n <motion.div\n layoutId=\"bottom-nav-indicator\"\n className=\"absolute top-0 h-[3px] w-full rounded-b-control-inner bg-accent-9 p-0\"\n aria-hidden=\"true\"\n transition={prefersReducedMotion ? { duration: 0 } : springs.snappy}\n />\n )}\n <div className=\"relative p-ds-03\">\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md\" aria-hidden=\"true\"><IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider></span>\n {item.badge != null && <NavBadge count={item.badge} />}\n </div>\n <span className=\"text-center\">{item.title}</span>\n </div>\n </Link>\n </motion.div>\n )\n}\n\n// -----------------------------------------------------------------------\n// BottomNavbar\n// -----------------------------------------------------------------------\n\nconst BottomNavbar = React.forwardRef<HTMLElement, BottomNavbarProps>(\n (\n {\n currentPath = '/',\n user: _user,\n primaryItems = [],\n moreItems = [],\n className,\n ...props\n },\n ref,\n ) => {\n const Link = useLink()\n const prefersReducedMotion = useReducedMotion()\n const [showMore, setShowMore] = useState(false)\n const overlayRef = useRef<HTMLDivElement>(null)\n\n const closeMore = useCallback(() => setShowMore(false), [])\n\n // Focus first focusable item when overlay opens\n useEffect(() => {\n if (showMore && overlayRef.current) {\n const firstFocusable = overlayRef.current.querySelector<HTMLElement>('a, button')\n firstFocusable?.focus()\n }\n }, [showMore])\n\n const isActive = (path: string, exact = false) => {\n if (exact || path === '/') {\n return currentPath === path\n }\n return currentPath.startsWith(path)\n }\n\n // Check if any \"more\" item is active\n const isMoreActive = moreItems.some((item) =>\n isActive(item.href, item.exact),\n )\n\n return (\n <>\n {/* More Menu Overlay */}\n <AnimatePresence>\n {showMore && (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events -- backdrop overlay, dismiss via mouse only; keyboard users close via Escape\n <div\n className=\"fixed inset-0 z-overlay md:hidden\"\n onClick={() => setShowMore(false)}\n >\n <div className=\"absolute inset-0 bg-overlay\" />\n { }\n <motion.div\n ref={overlayRef}\n role=\"dialog\"\n aria-label=\"More navigation\"\n initial={{ y: '100%' }}\n animate={{ y: 0 }}\n exit={{ y: '100%' }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n className=\"absolute bottom-[72px] left-0 right-0 rounded-t-bubble border-t border-surface-border-strong bg-surface-overlay p-ds-05 pb-ds-03\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n e.stopPropagation()\n if (e.key === 'Escape') closeMore()\n }}\n >\n <div className=\"mb-ds-04 flex items-center justify-between\">\n <span className=\"text-body-md font-semibold text-surface-fg\">\n More\n </span>\n <button\n onClick={() => setShowMore(false)}\n aria-label=\"Close more menu\"\n className=\"flex h-ds-sm w-ds-sm items-center justify-center rounded-pill hover:bg-surface-raised-hover\"\n >\n <Icon icon={IconX} size=\"sm\" className=\"text-surface-fg-muted\" />\n </button>\n </div>\n <div className=\"grid grid-cols-4 gap-ds-03\">\n {moreItems.map((item) => (\n <Link\n key={item.href}\n href={item.href}\n onClick={() => setShowMore(false)}\n className={cn(\n 'flex flex-col items-center gap-ds-02b rounded-overlay-lg p-ds-04 text-body-sm transition-colors ease-productive-standard',\n isActive(item.href, item.exact)\n ? 'bg-surface-raised-hover text-accent-11'\n : 'text-surface-fg-subtle hover:bg-surface-raised-hover',\n )}\n >\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md\"><IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider></span>\n <span className=\"text-center\">\n {item.title}\n </span>\n </Link>\n ))}\n </div>\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n\n {/* Bottom Navigation Bar */}\n <nav\n {...props}\n ref={ref}\n aria-label=\"Mobile navigation\"\n className={cn(\n 'fixed bottom-0 left-0 right-0 z-sticky flex w-full flex-row items-start justify-between border-t border-surface-border-strong bg-surface-chrome px-ds-05 pb-safe pt-0 md:hidden',\n className,\n )}\n >\n {primaryItems.map((item) => (\n <BottomNavLink\n key={item.href}\n item={item}\n isActive={isActive(item.href, item.exact)}\n />\n ))}\n\n {/* More Button */}\n {moreItems.length > 0 && (\n <motion.button\n type=\"button\"\n onClick={() => setShowMore(!showMore)}\n aria-label=\"More navigation options\"\n aria-expanded={showMore}\n whileTap={prefersReducedMotion ? undefined : { y: -2 }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.snappy}\n className={cn(\n 'flex h-16 max-w-[70px] flex-1 cursor-pointer flex-col items-center gap-ds-02 p-ds-02 pt-0 text-body-sm',\n showMore || isMoreActive\n ? 'font-semibold text-accent-11'\n : 'text-surface-fg-subtle',\n )}\n >\n <div className=\"relative flex w-full flex-col items-center gap-ds-02\">\n {(showMore || isMoreActive) && (\n <motion.div\n layoutId=\"bottom-nav-indicator\"\n className=\"absolute top-0 h-[3px] w-full rounded-b-control-inner bg-accent-9 p-0\"\n aria-hidden=\"true\"\n transition={prefersReducedMotion ? { duration: 0 } : springs.snappy}\n />\n )}\n <div className=\"p-ds-03\">\n <Icon icon={IconDots} />\n </div>\n <span className=\"text-center\">More</span>\n </div>\n </motion.button>\n )}\n </nav>\n </>\n )\n },\n)\nBottomNavbar.displayName = 'BottomNavbar'\n\nexport { BottomNavbar }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bottom-navbar.js","names":[],"sources":["../../src/shell/bottom-navbar.tsx"],"sourcesContent":["'use client'\n\n/**\n * BottomNavbar -- Mobile bottom navigation bar.\n *\n * Props-driven (currentPath / user / items) and router-agnostic via `useLink`.\n * The \"More\" overflow uses the DS `Sheet` primitive, so it inherits focus trap,\n * scroll lock, return-focus, `aria-modal`, and trigger↔panel ARIA wiring.\n */\nimport { IconDots } from '@tabler/icons-react'\nimport { motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\nimport { useState } from 'react'\n\nimport { Badge } from '../ui/badge'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '../ui/sheet'\nimport { useLink } from './link-context'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface BottomNavbarUser {\n name: string\n role?: string\n}\n\nexport interface BottomNavItem {\n title: string\n href: string\n /** Icon for this nav item. Accepts any `IconInput`. */\n icon: IconInput\n /** Icon shown when the item is active — e.g. a filled variant. Falls back to `icon`. */\n activeIcon?: IconInput\n /** When true, the route matches only when the path is exactly equal */\n exact?: boolean\n /** Notification badge count. 0 or undefined = hidden, 1–99 = shown, >99 = \"99+\" */\n badge?: number\n /**\n * Roles allowed to see this item, matched against `user.role`. Omit to show\n * it to everyone. For arbitrary logic, use `canView` instead.\n */\n roles?: string[]\n /**\n * Visibility predicate — full control over whether this item renders.\n * Receives the current `user` (or `null`). Takes precedence over `roles`.\n */\n canView?: (user: BottomNavbarUser | null) => boolean\n}\n\n/**\n * Active-item indicator, animated between items on selection:\n * - `pill` (default) — Material-3 tonal pill behind the icon\n * - `underline` — top accent bar (Material-2 tab style)\n * - `tint` — subtle background tint on the whole active cell\n * - `none` — no shape; rely on the filled `activeIcon` + accent color (iOS)\n */\nexport type BottomNavIndicator = 'pill' | 'underline' | 'tint' | 'none'\n/** Show labels always (default) or only for the selected item (narrow viewports). */\nexport type BottomNavLabelVisibility = 'always' | 'selected'\n\nexport interface BottomNavbarProps extends React.HTMLAttributes<HTMLElement> {\n /** Currently active pathname */\n currentPath?: string\n /** Current user. Drives per-item role gating via `item.roles` / `item.canView`. */\n user?: BottomNavbarUser | null\n /** Primary nav items shown directly in the bottom bar (max 4 recommended) */\n primaryItems?: BottomNavItem[]\n /** Additional items shown in the \"More\" overflow sheet */\n moreItems?: BottomNavItem[]\n /** Active-indicator style. @default 'pill' */\n indicator?: BottomNavIndicator\n /** Label visibility. @default 'always' */\n labelVisibility?: BottomNavLabelVisibility\n /** Additional className for the nav element */\n className?: string\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\n/** Per-item role/visibility gate. `canView` wins; else `roles` matched against user.role; else visible. */\nfunction itemVisible(item: BottomNavItem, user: BottomNavbarUser | null): boolean {\n if (item.canView) return item.canView(user)\n if (item.roles && item.roles.length > 0) {\n return !!user?.role && item.roles.includes(user.role)\n }\n return true\n}\n\n// -----------------------------------------------------------------------\n// NavBadge (composes Badge)\n// -----------------------------------------------------------------------\n\nfunction NavBadge({ count }: { count: number }) {\n if (!count || count <= 0) return null\n const display = count > 99 ? '99+' : String(count)\n return (\n <Badge\n color=\"error\"\n variant=\"solid\"\n size=\"xs\"\n aria-label={`${count} notifications`}\n className=\"pointer-events-none absolute -end-1 -top-1 justify-center px-ds-01 tabular-nums motion-safe:animate-in motion-safe:zoom-in-75\"\n >\n {display}\n </Badge>\n )\n}\n\n// -----------------------------------------------------------------------\n// Active indicator (shared-element)\n// -----------------------------------------------------------------------\n\n/**\n * The active-item indicator. A single shared-element (`layoutId`) that SLIDES\n * to the selected item and fades in on first appearance. `none` renders\n * nothing (the filled `activeIcon` + accent color carry the state).\n */\nfunction ActiveIndicator({\n indicator,\n layoutId,\n reduced,\n}: {\n indicator: BottomNavIndicator\n layoutId: string\n reduced: boolean\n}) {\n if (indicator === 'none') return null\n const common = {\n layoutId,\n 'aria-hidden': true as const,\n transition: reduced ? { duration: 0 } : springs.snappy,\n initial: reduced ? false : { opacity: 0 },\n animate: { opacity: 1 },\n }\n if (indicator === 'underline') {\n return <motion.span {...common} className=\"absolute top-0 h-[3px] w-full rounded-b-control-inner bg-accent-9\" />\n }\n if (indicator === 'tint') {\n return <motion.span {...common} className=\"absolute inset-0 rounded-control bg-accent-3\" />\n }\n // pill (default) — Material-3 tonal pill behind the icon\n return <motion.span {...common} className=\"absolute inset-0 rounded-pill bg-accent-3\" />\n}\n\n// -----------------------------------------------------------------------\n// BottomNavLink (internal)\n// -----------------------------------------------------------------------\n\nconst itemClass =\n 'relative flex h-16 w-full min-w-0 cursor-pointer flex-col items-center justify-center gap-ds-02 px-ds-01 pt-0 text-body-sm transition-colors duration-fast-02 ease-productive-standard'\n\nfunction BottomNavLink({\n item,\n isActive,\n indicator,\n indicatorId,\n showLabel,\n reduced,\n}: {\n item: BottomNavItem\n isActive: boolean\n indicator: BottomNavIndicator\n indicatorId: string\n showLabel: boolean\n reduced: boolean\n}) {\n const Link = useLink()\n return (\n <motion.div\n whileTap={reduced ? undefined : { scale: 0.96 }}\n transition={reduced ? { duration: 0 } : springs.snappy}\n className=\"flex min-w-0 flex-1 basis-0\"\n >\n <Link\n href={item.href}\n aria-label={item.title}\n aria-current={isActive ? 'page' : undefined}\n className={cn(itemClass, isActive ? 'font-semibold text-accent-11' : 'text-surface-fg-subtle')}\n >\n {/* tint covers the whole cell — sits behind the content */}\n {isActive && indicator === 'tint' && (\n <ActiveIndicator indicator=\"tint\" layoutId={indicatorId} reduced={reduced} />\n )}\n <div className=\"relative flex w-full min-w-0 flex-col items-center gap-ds-02\">\n {isActive && indicator === 'underline' && (\n <ActiveIndicator indicator=\"underline\" layoutId={indicatorId} reduced={reduced} />\n )}\n <div className=\"relative px-ds-04 py-ds-01\">\n {isActive && indicator === 'pill' && (\n <ActiveIndicator indicator=\"pill\" layoutId={indicatorId} reduced={reduced} />\n )}\n <span className=\"relative [&>svg]:h-ico-md [&>svg]:w-ico-md\" aria-hidden=\"true\">\n <IconProvider size=\"md\">\n {normalizeIcon(isActive && item.activeIcon ? item.activeIcon : item.icon)}\n </IconProvider>\n </span>\n {item.badge != null && <NavBadge count={item.badge} />}\n </div>\n {showLabel && <span className=\"max-w-full truncate text-center\">{item.title}</span>}\n </div>\n </Link>\n </motion.div>\n )\n}\n\n// -----------------------------------------------------------------------\n// BottomNavbar\n// -----------------------------------------------------------------------\n\nconst BottomNavbar = React.forwardRef<HTMLElement, BottomNavbarProps>(\n (\n {\n currentPath = '/',\n user = null,\n primaryItems = [],\n moreItems = [],\n indicator = 'pill',\n labelVisibility = 'always',\n className,\n ...props\n },\n ref,\n ) => {\n const Link = useLink()\n const reduced = useReducedMotion() ?? false\n const [showMore, setShowMore] = useState(false)\n // Scope the shared-element layoutId per instance so two navbars don't animate into each other.\n const instanceId = React.useId()\n const indicatorId = `${instanceId}-nav-indicator`\n\n const isActive = (path: string, exact = false) => {\n if (exact || path === '/') return currentPath === path\n return currentPath.startsWith(path)\n }\n\n // Role/visibility gating\n const visiblePrimary = primaryItems.filter((item) => itemVisible(item, user))\n const visibleMore = moreItems.filter((item) => itemVisible(item, user))\n\n const isMoreActive = visibleMore.some((item) => isActive(item.href, item.exact))\n const moreSelected = showMore || isMoreActive\n const showMoreLabel = labelVisibility === 'always' || moreSelected\n\n return (\n <nav\n {...props}\n ref={ref}\n aria-label=\"Mobile navigation\"\n className={cn(\n 'fixed bottom-0 start-0 end-0 z-sticky flex w-full flex-row items-stretch justify-between border-t border-surface-border-strong bg-surface-chrome px-ds-05 pb-safe pt-0 md:hidden',\n className,\n )}\n >\n {visiblePrimary.map((item) => (\n <BottomNavLink\n key={item.href}\n item={item}\n isActive={isActive(item.href, item.exact)}\n indicator={indicator}\n indicatorId={indicatorId}\n showLabel={labelVisibility === 'always' || isActive(item.href, item.exact)}\n reduced={reduced}\n />\n ))}\n\n {visibleMore.length > 0 && (\n <Sheet open={showMore} onOpenChange={setShowMore}>\n <SheetTrigger asChild>\n <motion.button\n type=\"button\"\n aria-label=\"More navigation options\"\n whileTap={reduced ? undefined : { scale: 0.96 }}\n transition={reduced ? { duration: 0 } : springs.snappy}\n className={cn(\n itemClass,\n 'min-w-0 flex-1 basis-0',\n moreSelected ? 'font-semibold text-accent-11' : 'text-surface-fg-subtle',\n )}\n >\n {moreSelected && indicator === 'tint' && (\n <ActiveIndicator indicator=\"tint\" layoutId={indicatorId} reduced={reduced} />\n )}\n <div className=\"relative flex w-full min-w-0 flex-col items-center gap-ds-02\">\n {moreSelected && indicator === 'underline' && (\n <ActiveIndicator indicator=\"underline\" layoutId={indicatorId} reduced={reduced} />\n )}\n <div className=\"relative px-ds-04 py-ds-01\">\n {moreSelected && indicator === 'pill' && (\n <ActiveIndicator indicator=\"pill\" layoutId={indicatorId} reduced={reduced} />\n )}\n <Icon icon={IconDots} />\n </div>\n {showMoreLabel && <span className=\"max-w-full truncate text-center\">More</span>}\n </div>\n </motion.button>\n </SheetTrigger>\n\n <SheetContent side=\"bottom\" className=\"rounded-t-bubble\">\n <SheetHeader>\n <SheetTitle>More</SheetTitle>\n </SheetHeader>\n <div className=\"grid grid-cols-[repeat(auto-fit,minmax(72px,1fr))] gap-ds-03 pt-ds-04\">\n {visibleMore.map((item) => {\n const active = isActive(item.href, item.exact)\n return (\n <Link\n key={item.href}\n href={item.href}\n onClick={() => setShowMore(false)}\n aria-current={active ? 'page' : undefined}\n className={cn(\n 'flex min-w-0 flex-col items-center gap-ds-02b rounded-overlay-lg p-ds-04 text-body-sm transition-colors ease-productive-standard',\n active\n ? 'bg-surface-raised-hover text-accent-11'\n : 'text-surface-fg-subtle hover:bg-surface-raised-hover',\n )}\n >\n <span className=\"[&>svg]:h-ico-md [&>svg]:w-ico-md\" aria-hidden=\"true\">\n <IconProvider size=\"md\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n <span className=\"max-w-full truncate text-center\">{item.title}</span>\n </Link>\n )\n })}\n </div>\n </SheetContent>\n </Sheet>\n )}\n </nav>\n )\n },\n)\nBottomNavbar.displayName = 'BottomNavbar'\n\nexport { BottomNavbar }\n"],"mappings":"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"}
|
|
@@ -49,7 +49,9 @@
|
|
|
49
49
|
|
|
50
50
|
/* ── Neutral — Warm grays — H:350 ── */
|
|
51
51
|
--neutral-0: #ffffff;
|
|
52
|
-
|
|
52
|
+
/* Sunken well. Chroma follows the neutral cadence (was H:360 C:0.008 — an
|
|
53
|
+
outlier that read visibly pink on sunken surfaces). */
|
|
54
|
+
--color-surface-0: oklch(0.945 0.0013 350);
|
|
53
55
|
--neutral-1: oklch(0.99 0.0003 350);
|
|
54
56
|
--neutral-2: oklch(0.97 0.0008 350);
|
|
55
57
|
--neutral-3: oklch(0.93 0.0018 350);
|
|
@@ -262,7 +264,9 @@
|
|
|
262
264
|
--purple-12: oklch(0.88 0.0316 300);
|
|
263
265
|
|
|
264
266
|
/* ── Neutral — Warm grays — H:350 ── */
|
|
265
|
-
|
|
267
|
+
/* Sunken well (deep). Chroma follows the neutral cadence — was H:360 C:0.008,
|
|
268
|
+
an outlier that read tinted rather than neutral. */
|
|
269
|
+
--color-surface-0: oklch(0.07 0.0004 350);
|
|
266
270
|
--neutral-1: oklch(0.11 0.0002 350);
|
|
267
271
|
--neutral-2: oklch(0.17 0.0007 350);
|
|
268
272
|
--neutral-3: oklch(0.23 0.0019 350);
|
|
@@ -340,3 +340,9 @@
|
|
|
340
340
|
─────────────────────────────────────────────────────────────────── */
|
|
341
341
|
|
|
342
342
|
@utility border-card { border-color: var(--color-surface-border-card); }
|
|
343
|
+
/* Stronger card edge (kbd caps, code blocks, skeleton/panel outlines, chip
|
|
344
|
+
borders) — one step up from the faint `border-card` mix. Dark-mode aware via
|
|
345
|
+
the semantic token. Was referenced in ~11 components with no matching utility
|
|
346
|
+
(dead class → border fell back to currentColor); defined here to restore the
|
|
347
|
+
intended hairline. */
|
|
348
|
+
@utility border-card-strong { border-color: var(--color-surface-border); }
|
|
@@ -1,59 +1,61 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { InputProps } from './input';
|
|
2
3
|
import * as React from 'react';
|
|
3
|
-
type AutocompleteOption = {
|
|
4
|
+
export type AutocompleteOption = {
|
|
4
5
|
label: string;
|
|
5
6
|
value: string;
|
|
6
7
|
};
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* A free-text input with a live-filtered dropdown, keyboard navigation, and
|
|
10
|
+
* combobox ARIA. The field itself is the DS `Input`, so it inherits size,
|
|
11
|
+
* error/state painting, read-only, hover, and FormField wiring.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* with suggestions; use Combobox for structured single or multi-select dropdowns.
|
|
15
|
-
*
|
|
16
|
-
* **`value`:** A full `AutocompleteOption` object (or null), not just the string value.
|
|
17
|
-
* The input's text is synced to `value.label` on mount.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* // City search autocomplete:
|
|
21
|
-
* <Autocomplete
|
|
22
|
-
* options={[{ value: 'mumbai', label: 'Mumbai' }, { value: 'delhi', label: 'Delhi' }]}
|
|
23
|
-
* value={selectedCity}
|
|
24
|
-
* onValueChange={(opt) => setSelectedCity(opt)}
|
|
25
|
-
* placeholder="Search cities..."
|
|
26
|
-
* />
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* // Employee name lookup with custom empty text:
|
|
30
|
-
* <Autocomplete
|
|
31
|
-
* options={employees.map(e => ({ value: e.id, label: e.fullName }))}
|
|
32
|
-
* onValueChange={(opt) => setAssignee(opt.value)}
|
|
33
|
-
* emptyText="No employees found"
|
|
34
|
-
* placeholder="Search employees..."
|
|
35
|
-
* />
|
|
36
|
-
* // These are just a few ways — feel free to combine props creatively!
|
|
13
|
+
* Free-text (no forced selection) — for enforced selection use `Combobox`.
|
|
14
|
+
* `value`/`defaultValue` are a full `AutocompleteOption` (or null).
|
|
37
15
|
*/
|
|
38
|
-
type AutocompleteProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
16
|
+
export type AutocompleteProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
|
|
39
17
|
options: AutocompleteOption[];
|
|
18
|
+
/** Controlled selection. */
|
|
40
19
|
value?: AutocompleteOption | null;
|
|
20
|
+
/** Initial selection for uncontrolled mode. */
|
|
21
|
+
defaultValue?: AutocompleteOption | null;
|
|
41
22
|
onValueChange?: (option: AutocompleteOption) => void;
|
|
42
23
|
placeholder?: string;
|
|
43
24
|
emptyText?: string;
|
|
44
25
|
disabled?: boolean;
|
|
26
|
+
/** Input size (forwarded to the composed `Input`). */
|
|
27
|
+
size?: InputProps['size'];
|
|
28
|
+
/** Field state (forwarded to `Input`); overrides FormField auto-consumption. */
|
|
29
|
+
state?: InputProps['state'];
|
|
30
|
+
/** Show a loading spinner + `loadingText` (async "type to search"). */
|
|
31
|
+
isLoading?: boolean;
|
|
32
|
+
loadingText?: string;
|
|
33
|
+
/** Custom option renderer. Receives the option and the current query. */
|
|
34
|
+
renderOption?: (option: AutocompleteOption, query: string) => React.ReactNode;
|
|
45
35
|
className?: string;
|
|
46
36
|
id?: string;
|
|
47
37
|
};
|
|
48
|
-
declare const Autocomplete: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
38
|
+
declare const Autocomplete: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> & {
|
|
49
39
|
options: AutocompleteOption[];
|
|
40
|
+
/** Controlled selection. */
|
|
50
41
|
value?: AutocompleteOption | null;
|
|
42
|
+
/** Initial selection for uncontrolled mode. */
|
|
43
|
+
defaultValue?: AutocompleteOption | null;
|
|
51
44
|
onValueChange?: (option: AutocompleteOption) => void;
|
|
52
45
|
placeholder?: string;
|
|
53
46
|
emptyText?: string;
|
|
54
47
|
disabled?: boolean;
|
|
48
|
+
/** Input size (forwarded to the composed `Input`). */
|
|
49
|
+
size?: InputProps["size"];
|
|
50
|
+
/** Field state (forwarded to `Input`); overrides FormField auto-consumption. */
|
|
51
|
+
state?: InputProps["state"];
|
|
52
|
+
/** Show a loading spinner + `loadingText` (async "type to search"). */
|
|
53
|
+
isLoading?: boolean;
|
|
54
|
+
loadingText?: string;
|
|
55
|
+
/** Custom option renderer. Receives the option and the current query. */
|
|
56
|
+
renderOption?: (option: AutocompleteOption, query: string) => React.ReactNode;
|
|
55
57
|
className?: string;
|
|
56
58
|
id?: string;
|
|
57
59
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
58
|
-
export { Autocomplete
|
|
60
|
+
export { Autocomplete };
|
|
59
61
|
//# sourceMappingURL=autocomplete.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../src/ui/autocomplete.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../src/ui/autocomplete.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,SAAS,CAAA;AAKhD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACvF,OAAO,EAAE,kBAAkB,EAAE,CAAA;IAC7B,4BAA4B;IAC5B,KAAK,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACxC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAA;IACpD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sDAAsD;IACtD,IAAI,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;IACzB,gFAAgF;IAChF,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;IAC3B,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yEAAyE;IACzE,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAA;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ,CAAA;AAeD,QAAA,MAAM,YAAY;aAnCP,kBAAkB,EAAE;IAC7B,4BAA4B;YACpB,kBAAkB,GAAG,IAAI;IACjC,+CAA+C;mBAChC,kBAAkB,GAAG,IAAI;oBACxB,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI;kBACtC,MAAM;gBACR,MAAM;eACP,OAAO;IAClB,sDAAsD;WAC/C,UAAU,CAAC,MAAM,CAAC;IACzB,gFAAgF;YACxE,UAAU,CAAC,OAAO,CAAC;IAC3B,uEAAuE;gBAC3D,OAAO;kBACL,MAAM;IACpB,yEAAyE;mBAC1D,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS;gBACjE,MAAM;SACb,MAAM;0CA2PZ,CAAA;AAGD,OAAO,EAAE,YAAY,EAAE,CAAA"}
|