@devalok/shilp-sutra 0.39.0 → 0.40.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/AGENTS.md +151 -0
- package/MIGRATION.md +137 -0
- package/README.md +3 -0
- package/dist/_chunks/badge-group.js +75 -74
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/chart-container.js +50 -0
- package/dist/_chunks/chart-container.js.map +1 -0
- package/dist/_chunks/chat.js +231 -223
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/colors.js +30 -0
- package/dist/_chunks/colors.js.map +1 -0
- package/dist/_chunks/emoji-data.js +45 -0
- package/dist/_chunks/emoji-data.js.map +1 -0
- package/dist/_chunks/grid-lines.js +72 -0
- package/dist/_chunks/grid-lines.js.map +1 -0
- package/dist/_chunks/mention-suggestion.js +31 -259
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/normalize-icon.js +18 -0
- package/dist/_chunks/normalize-icon.js.map +1 -0
- package/dist/_chunks/oauth-button.js +227 -0
- package/dist/_chunks/oauth-button.js.map +1 -0
- package/dist/_chunks/primitives.js +107 -107
- package/dist/_chunks/primitives.js.map +1 -1
- package/dist/_chunks/{text.js → success.js} +24 -61
- package/dist/_chunks/success.js.map +1 -0
- package/dist/_chunks/tiptap.js +1952 -1949
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/_chunks/tooltip.js +58 -0
- package/dist/_chunks/tooltip.js.map +1 -0
- package/dist/_chunks/tree-view.js +101 -96
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/ai/ai-command-provider.d.ts +3 -2
- package/dist/ai/ai-command-provider.d.ts.map +1 -1
- package/dist/ai/ai-command-provider.js.map +1 -1
- package/dist/ai/block-renderer.js +11 -9
- package/dist/ai/block-renderer.js.map +1 -1
- package/dist/ai/blocks/error.js +31 -0
- package/dist/ai/blocks/error.js.map +1 -0
- package/dist/ai/blocks/index.d.ts +0 -2
- package/dist/ai/blocks/index.d.ts.map +1 -1
- package/dist/ai/blocks/index.js +2 -2
- package/dist/ai/blocks/text.js +19 -0
- package/dist/ai/blocks/text.js.map +1 -0
- package/dist/ai/command-bar.d.ts.map +1 -1
- package/dist/ai/command-bar.js +192 -187
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.d.ts +2 -1
- package/dist/ai/conversation.d.ts.map +1 -1
- package/dist/ai/conversation.js +88 -83
- package/dist/ai/conversation.js.map +1 -1
- package/dist/ai/index.d.ts +0 -4
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +45 -46
- package/dist/ai/index.js.map +1 -1
- package/dist/composed/activity-feed.d.ts +2 -1
- package/dist/composed/activity-feed.d.ts.map +1 -1
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/bulk-action-bar.d.ts +2 -2
- package/dist/composed/bulk-action-bar.d.ts.map +1 -1
- package/dist/composed/bulk-action-bar.js +11 -11
- package/dist/composed/bulk-action-bar.js.map +1 -1
- package/dist/composed/command-palette.d.ts +2 -1
- package/dist/composed/command-palette.d.ts.map +1 -1
- package/dist/composed/command-palette.js +103 -98
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/date-picker/index.js +747 -3
- package/dist/composed/date-picker/index.js.map +1 -0
- package/dist/composed/empty-state.d.ts +3 -3
- package/dist/composed/empty-state.d.ts.map +1 -1
- package/dist/composed/empty-state.js +40 -31
- package/dist/composed/empty-state.js.map +1 -1
- package/dist/composed/extensions/emoji-node.js +81 -0
- package/dist/composed/extensions/emoji-node.js.map +1 -0
- package/dist/composed/extensions/emoji-suggestion.js +117 -0
- package/dist/composed/extensions/emoji-suggestion.js.map +1 -0
- package/dist/composed/file-preview.js +498 -2
- package/dist/{_chunks → composed}/file-preview.js.map +1 -1
- package/dist/composed/index.d.ts +0 -15
- package/dist/composed/index.d.ts.map +1 -1
- package/dist/composed/index.js +16 -24
- package/dist/composed/rich-chat-input.js +2073 -2
- package/dist/{_chunks → composed}/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.js +64 -61
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/status-badge.d.ts +3 -2
- package/dist/composed/status-badge.d.ts.map +1 -1
- package/dist/composed/status-badge.js +58 -53
- package/dist/composed/status-badge.js.map +1 -1
- package/dist/shell/app-command-palette.d.ts +2 -1
- package/dist/shell/app-command-palette.d.ts.map +1 -1
- package/dist/shell/app-command-palette.js.map +1 -1
- package/dist/shell/bottom-navbar.d.ts +3 -1
- package/dist/shell/bottom-navbar.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.js +90 -82
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/command-registry.d.ts +2 -1
- package/dist/shell/command-registry.d.ts.map +1 -1
- package/dist/shell/command-registry.js.map +1 -1
- package/dist/shell/sidebar.d.ts +7 -4
- package/dist/shell/sidebar.d.ts.map +1 -1
- package/dist/shell/sidebar.js +143 -129
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/top-bar.d.ts +4 -3
- package/dist/shell/top-bar.d.ts.map +1 -1
- package/dist/shell/top-bar.js +114 -106
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/ui/badge.d.ts +3 -2
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/button.d.ts +3 -2
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +54 -53
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/charts/area-chart.js +177 -0
- package/dist/ui/charts/area-chart.js.map +1 -0
- package/dist/ui/charts/bar-chart.js +127 -0
- package/dist/ui/charts/bar-chart.js.map +1 -0
- package/dist/ui/charts/chart-container.js +3 -0
- package/dist/ui/charts/gauge-chart.js +72 -0
- package/dist/ui/charts/gauge-chart.js.map +1 -0
- package/dist/ui/charts/index.js +10 -1035
- package/dist/ui/charts/line-chart.js +135 -0
- package/dist/ui/charts/line-chart.js.map +1 -0
- package/dist/ui/charts/pie-chart.js +111 -0
- package/dist/ui/charts/pie-chart.js.map +1 -0
- package/dist/ui/charts/radar-chart.js +170 -0
- package/dist/ui/charts/radar-chart.js.map +1 -0
- package/dist/ui/charts/sparkline.js +119 -0
- package/dist/ui/charts/sparkline.js.map +1 -0
- package/dist/ui/chat/message.d.ts +3 -3
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/chat/system-message.d.ts +2 -1
- package/dist/ui/chat/system-message.d.ts.map +1 -1
- package/dist/ui/combobox.d.ts +2 -1
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +97 -92
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/container.d.ts +6 -1
- package/dist/ui/container.d.ts.map +1 -1
- package/dist/ui/container.js +2 -1
- package/dist/ui/container.js.map +1 -1
- package/dist/ui/icon-button.d.ts +9 -2
- package/dist/ui/icon-button.d.ts.map +1 -1
- package/dist/ui/icon-button.js +14 -13
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/index.d.ts +1 -3
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +31 -33
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/lib/icon-input.d.ts +42 -0
- package/dist/ui/lib/icon-input.d.ts.map +1 -0
- package/dist/ui/lib/normalize-icon.d.ts +39 -0
- package/dist/ui/lib/normalize-icon.d.ts.map +1 -0
- package/dist/ui/oauth-button/index.d.ts +3 -0
- package/dist/ui/oauth-button/index.d.ts.map +1 -0
- package/dist/ui/oauth-button/index.js +3 -0
- package/dist/ui/oauth-button/oauth-button.d.ts +208 -0
- package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -0
- package/dist/ui/progress.js +1 -1
- package/dist/ui/segmented-control.d.ts +3 -4
- package/dist/ui/segmented-control.d.ts.map +1 -1
- package/dist/ui/segmented-control.js +53 -45
- package/dist/ui/segmented-control.js.map +1 -1
- package/dist/ui/stack.d.ts +6 -1
- package/dist/ui/stack.d.ts.map +1 -1
- package/dist/ui/stack.js +2 -1
- package/dist/ui/stack.js.map +1 -1
- package/dist/ui/stat-card.d.ts +2 -3
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +117 -115
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stepper.d.ts +2 -1
- package/dist/ui/stepper.d.ts.map +1 -1
- package/dist/ui/stepper.js +74 -69
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/text.d.ts +7 -2
- package/dist/ui/text.d.ts.map +1 -1
- package/dist/ui/text.js +2 -1
- package/dist/ui/text.js.map +1 -1
- package/dist/ui/toaster.d.ts +11 -2
- package/dist/ui/toaster.d.ts.map +1 -1
- package/dist/ui/toaster.js.map +1 -1
- package/dist/ui/tooltip.js +12 -12
- package/dist/ui/tree-view/tree-item.d.ts +3 -2
- package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
- package/dist/ui/tree-view/use-tree.d.ts +2 -1
- package/dist/ui/tree-view/use-tree.d.ts.map +1 -1
- package/docs/components/ui/oauth-button.md +86 -0
- package/docs/recipes/customize-brand.md +15 -0
- package/docs/recipes/index.md +5 -1
- package/docs/recipes/install-astro.md +15 -0
- package/docs/recipes/install-next-app-router.md +21 -5
- package/docs/recipes/install-next-pages.md +2 -0
- package/docs/recipes/install-remix.md +15 -0
- package/docs/recipes/install-tanstack-start.md +15 -0
- package/docs/recipes/install-vite.md +15 -0
- package/docs/recipes/troubleshoot.md +22 -0
- package/llms-full.txt +87 -1
- package/llms-quick.txt +247 -0
- package/llms.txt +107 -2
- package/package.json +79 -2
- package/scripts/welcome.mjs +219 -0
- package/skill/SKILL.md +22 -3
- package/skill/references/components-full.md +87 -1
- package/skill/references/components.md +107 -2
- package/skill/references/customize-brand.md +15 -0
- package/skill/references/setup-astro.md +15 -0
- package/skill/references/setup-next-app-router.md +21 -5
- package/skill/references/setup-next-pages.md +2 -0
- package/skill/references/setup-remix.md +15 -0
- package/skill/references/setup-tanstack-start.md +15 -0
- package/skill/references/setup-vite.md +15 -0
- package/skill/references/troubleshoot.md +22 -0
- package/dist/_chunks/date-picker.js +0 -748
- package/dist/_chunks/date-picker.js.map +0 -1
- package/dist/_chunks/file-preview.js +0 -499
- package/dist/_chunks/rich-chat-input.js +0 -2071
- package/dist/_chunks/text.js.map +0 -1
- package/dist/ui/charts/index.js.map +0 -1
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { t } from "../
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
2
|
+
import { IconProvider as e } from "../ui/icon-context.js";
|
|
3
|
+
import { motionProps as t } from "../ui/lib/motion.js";
|
|
4
|
+
import { t as n } from "../_chunks/vendor-utils.js";
|
|
5
|
+
import { cn as r } from "../ui/lib/utils.js";
|
|
6
|
+
import { Icon as i } from "../ui/icon.js";
|
|
7
|
+
import { t as a } from "../_chunks/normalize-icon.js";
|
|
8
|
+
import * as o from "react";
|
|
9
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
10
|
+
import { IconChevronDown as l } from "@tabler/icons-react";
|
|
11
|
+
import { AnimatePresence as u, motion as d } from "framer-motion";
|
|
10
12
|
//#region src/composed/status-badge.tsx
|
|
11
|
-
var
|
|
13
|
+
var f = n("inline-flex items-center gap-ds-02b rounded-pill font-body", {
|
|
12
14
|
variants: {
|
|
13
15
|
status: {
|
|
14
16
|
active: "bg-success-3 text-success-11",
|
|
@@ -35,7 +37,7 @@ var u = t("inline-flex items-center gap-ds-02b rounded-pill font-body", {
|
|
|
35
37
|
}
|
|
36
38
|
},
|
|
37
39
|
defaultVariants: { size: "md" }
|
|
38
|
-
}),
|
|
40
|
+
}), p = {
|
|
39
41
|
active: "bg-success-9",
|
|
40
42
|
pending: "bg-warning-9",
|
|
41
43
|
approved: "bg-success-9",
|
|
@@ -46,30 +48,33 @@ var u = t("inline-flex items-center gap-ds-02b rounded-pill font-body", {
|
|
|
46
48
|
review: "bg-info-9",
|
|
47
49
|
cancelled: "bg-disabled",
|
|
48
50
|
draft: "bg-surface-fg-subtle"
|
|
49
|
-
},
|
|
51
|
+
}, m = {
|
|
50
52
|
success: "bg-success-9",
|
|
51
53
|
warning: "bg-warning-9",
|
|
52
54
|
error: "bg-error-9",
|
|
53
55
|
info: "bg-info-9",
|
|
54
56
|
neutral: "bg-surface-fg-subtle"
|
|
55
|
-
},
|
|
57
|
+
}, h = {
|
|
56
58
|
duration: .3,
|
|
57
59
|
ease: "easeOut"
|
|
58
|
-
},
|
|
59
|
-
let
|
|
60
|
-
icon:
|
|
60
|
+
}, g = o.forwardRef(({ status: n, color: o, size: g, label: _, hideDot: v = !1, onClick: y, icon: b, className: x, ...S }, C) => {
|
|
61
|
+
let w = y != null, T = w ? d.button : d.span, E = w ? "cursor-pointer hover:opacity-80 transition-opacity" : void 0, D = b == null ? w ? /* @__PURE__ */ s(i, {
|
|
62
|
+
icon: l,
|
|
61
63
|
size: "xs",
|
|
62
64
|
className: "text-current/50 -mr-0.5 shrink-0"
|
|
63
|
-
}) : null
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
}) : null : /* @__PURE__ */ s(e, {
|
|
66
|
+
size: "xs",
|
|
67
|
+
children: a(b)
|
|
68
|
+
});
|
|
69
|
+
if (o != null) {
|
|
70
|
+
let e = _ ?? o.charAt(0).toUpperCase() + o.slice(1), n = m[o];
|
|
71
|
+
return /* @__PURE__ */ s(u, {
|
|
67
72
|
mode: "wait",
|
|
68
|
-
children: /* @__PURE__ */
|
|
69
|
-
ref:
|
|
70
|
-
...
|
|
73
|
+
children: /* @__PURE__ */ c(T, {
|
|
74
|
+
ref: C,
|
|
75
|
+
...w ? {
|
|
71
76
|
type: "button",
|
|
72
|
-
onClick:
|
|
77
|
+
onClick: y
|
|
73
78
|
} : {},
|
|
74
79
|
initial: {
|
|
75
80
|
opacity: .6,
|
|
@@ -83,52 +88,52 @@ var u = t("inline-flex items-center gap-ds-02b rounded-pill font-body", {
|
|
|
83
88
|
opacity: .6,
|
|
84
89
|
scale: .95
|
|
85
90
|
},
|
|
86
|
-
transition:
|
|
87
|
-
className:
|
|
88
|
-
color:
|
|
89
|
-
size:
|
|
90
|
-
}),
|
|
91
|
-
...
|
|
91
|
+
transition: h,
|
|
92
|
+
className: r(f({
|
|
93
|
+
color: o,
|
|
94
|
+
size: g
|
|
95
|
+
}), E, x),
|
|
96
|
+
...t(S),
|
|
92
97
|
children: [
|
|
93
|
-
!
|
|
94
|
-
className:
|
|
98
|
+
!v && /* @__PURE__ */ s("span", {
|
|
99
|
+
className: r("shrink-0 rounded-pill", g === "sm" ? "h-ds-02b w-ds-02b" : "h-[8px] w-[8px]", n),
|
|
95
100
|
"aria-hidden": "true"
|
|
96
101
|
}),
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
e,
|
|
103
|
+
D
|
|
99
104
|
]
|
|
100
|
-
},
|
|
105
|
+
}, o)
|
|
101
106
|
});
|
|
102
107
|
}
|
|
103
|
-
let
|
|
104
|
-
return /* @__PURE__ */
|
|
108
|
+
let O = n ?? "pending", k = _ ?? O.charAt(0).toUpperCase() + O.slice(1), A = p[O];
|
|
109
|
+
return /* @__PURE__ */ s(u, {
|
|
105
110
|
mode: "wait",
|
|
106
|
-
children: /* @__PURE__ */
|
|
107
|
-
ref:
|
|
108
|
-
...
|
|
111
|
+
children: /* @__PURE__ */ c(T, {
|
|
112
|
+
ref: C,
|
|
113
|
+
...w ? {
|
|
109
114
|
type: "button",
|
|
110
|
-
onClick:
|
|
115
|
+
onClick: y
|
|
111
116
|
} : {},
|
|
112
117
|
initial: { opacity: .6 },
|
|
113
118
|
animate: { opacity: 1 },
|
|
114
119
|
exit: { opacity: .6 },
|
|
115
|
-
transition:
|
|
116
|
-
className:
|
|
117
|
-
status:
|
|
118
|
-
size:
|
|
119
|
-
}),
|
|
120
|
-
...
|
|
120
|
+
transition: h,
|
|
121
|
+
className: r(f({
|
|
122
|
+
status: O,
|
|
123
|
+
size: g
|
|
124
|
+
}), E, x),
|
|
125
|
+
...t(S),
|
|
121
126
|
children: [
|
|
122
|
-
!
|
|
123
|
-
className:
|
|
127
|
+
!v && /* @__PURE__ */ s("span", {
|
|
128
|
+
className: r("shrink-0 rounded-pill", g === "sm" ? "h-ds-02b w-ds-02b" : "h-[8px] w-[8px]", A),
|
|
124
129
|
"aria-hidden": "true"
|
|
125
130
|
}),
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
k,
|
|
132
|
+
D
|
|
128
133
|
]
|
|
129
|
-
},
|
|
134
|
+
}, O)
|
|
130
135
|
});
|
|
131
136
|
});
|
|
132
|
-
|
|
137
|
+
g.displayName = "StatusBadge";
|
|
133
138
|
//#endregion
|
|
134
|
-
export {
|
|
139
|
+
export { g as StatusBadge, f as statusBadgeVariants };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-badge.js","names":[],"sources":["../../src/composed/status-badge.tsx"],"sourcesContent":["'use client'\n\nimport { IconChevronDown } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from '../ui/icon'\nimport { motionProps } from '../ui/lib/motion'\nimport { cn } from '../ui/lib/utils'\n\nconst statusBadgeVariants = cva(\n 'inline-flex items-center gap-ds-02b rounded-pill font-body',\n {\n variants: {\n status: {\n active: 'bg-success-3 text-success-11',\n pending: 'bg-warning-3 text-warning-11',\n approved: 'bg-success-3 text-success-11',\n rejected: 'bg-error-3 text-error-11',\n completed: 'bg-success-3 text-success-11',\n blocked: 'bg-error-3 text-error-11',\n 'in-progress': 'bg-accent-3 text-accent-11',\n review: 'bg-info-3 text-info-11',\n cancelled: 'bg-surface-raised text-surface-fg-subtle',\n draft: 'bg-surface-raised text-surface-fg-subtle',\n },\n color: {\n success: 'bg-success-3 text-success-11',\n warning: 'bg-warning-3 text-warning-11',\n error: 'bg-error-3 text-error-11',\n info: 'bg-info-3 text-info-11',\n neutral: 'bg-surface-raised text-surface-fg-subtle',\n },\n size: {\n sm: 'px-ds-03 py-ds-01 text-ds-xs font-semibold',\n md: 'px-ds-04 py-ds-02 text-ds-sm font-medium',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n)\n\nconst dotColorMap: Record<string, string> = {\n active: 'bg-success-9',\n pending: 'bg-warning-9',\n approved: 'bg-success-9',\n rejected: 'bg-error-9',\n completed: 'bg-success-9',\n blocked: 'bg-error-9',\n 'in-progress': 'bg-accent-9',\n review: 'bg-info-9',\n cancelled: 'bg-disabled',\n draft: 'bg-surface-fg-subtle',\n}\n\nconst colorDotMap: Record<string, string> = {\n success: 'bg-success-9',\n warning: 'bg-warning-9',\n error: 'bg-error-9',\n info: 'bg-info-9',\n neutral: 'bg-surface-fg-subtle',\n}\n\ninterface StatusBadgeBaseProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children' | 'color'> {\n label?: string\n hideDot?: boolean\n size?: VariantProps<typeof statusBadgeVariants>['size']\n onClick?: () => void\n icon?:
|
|
1
|
+
{"version":3,"file":"status-badge.js","names":[],"sources":["../../src/composed/status-badge.tsx"],"sourcesContent":["'use client'\n\nimport { IconChevronDown } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { motionProps } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\n\nconst statusBadgeVariants = cva(\n 'inline-flex items-center gap-ds-02b rounded-pill font-body',\n {\n variants: {\n status: {\n active: 'bg-success-3 text-success-11',\n pending: 'bg-warning-3 text-warning-11',\n approved: 'bg-success-3 text-success-11',\n rejected: 'bg-error-3 text-error-11',\n completed: 'bg-success-3 text-success-11',\n blocked: 'bg-error-3 text-error-11',\n 'in-progress': 'bg-accent-3 text-accent-11',\n review: 'bg-info-3 text-info-11',\n cancelled: 'bg-surface-raised text-surface-fg-subtle',\n draft: 'bg-surface-raised text-surface-fg-subtle',\n },\n color: {\n success: 'bg-success-3 text-success-11',\n warning: 'bg-warning-3 text-warning-11',\n error: 'bg-error-3 text-error-11',\n info: 'bg-info-3 text-info-11',\n neutral: 'bg-surface-raised text-surface-fg-subtle',\n },\n size: {\n sm: 'px-ds-03 py-ds-01 text-ds-xs font-semibold',\n md: 'px-ds-04 py-ds-02 text-ds-sm font-medium',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n)\n\nconst dotColorMap: Record<string, string> = {\n active: 'bg-success-9',\n pending: 'bg-warning-9',\n approved: 'bg-success-9',\n rejected: 'bg-error-9',\n completed: 'bg-success-9',\n blocked: 'bg-error-9',\n 'in-progress': 'bg-accent-9',\n review: 'bg-info-9',\n cancelled: 'bg-disabled',\n draft: 'bg-surface-fg-subtle',\n}\n\nconst colorDotMap: Record<string, string> = {\n success: 'bg-success-9',\n warning: 'bg-warning-9',\n error: 'bg-error-9',\n info: 'bg-info-9',\n neutral: 'bg-surface-fg-subtle',\n}\n\ninterface StatusBadgeBaseProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children' | 'color'> {\n label?: string\n hideDot?: boolean\n size?: VariantProps<typeof statusBadgeVariants>['size']\n onClick?: () => void\n icon?: IconInput\n}\n\ninterface StatusBadgeWithStatus extends StatusBadgeBaseProps {\n status?: VariantProps<typeof statusBadgeVariants>['status']\n color?: never\n}\n\ninterface StatusBadgeWithColor extends StatusBadgeBaseProps {\n status?: never\n color: 'success' | 'warning' | 'error' | 'info' | 'neutral'\n}\n\nexport type StatusBadgeProps = StatusBadgeWithStatus | StatusBadgeWithColor\n\n/* Between durations.moderate02 (0.24) and durations.slow01 (0.4) — intentional for smooth morph */\nconst statusMorphTransition = { duration: 0.3, ease: 'easeOut' as const }\n\nconst StatusBadge = React.forwardRef<HTMLSpanElement, StatusBadgeProps>(\n ({ status, color, size, label, hideDot = false, onClick, icon, className, ...props }, ref) => {\n const isClickable = onClick != null\n const Tag = isClickable ? motion.button : motion.span\n const clickableClasses = isClickable ? 'cursor-pointer hover:opacity-80 transition-opacity' : undefined\n\n const trailingIcon = icon != null\n ? <IconProvider size=\"xs\">{normalizeIcon(icon)}</IconProvider>\n : isClickable\n ? <Icon icon={IconChevronDown} size=\"xs\" className=\"text-current/50 -mr-0.5 shrink-0\" />\n : null\n\n if (color != null) {\n // Color branch — color is the styling key\n const displayLabel = label ?? (color.charAt(0).toUpperCase() + color.slice(1))\n const dotColor = colorDotMap[color]\n\n return (\n <AnimatePresence mode=\"wait\">\n <Tag\n key={color}\n ref={ref as any}\n {...(isClickable ? { type: 'button' as const, onClick } : {})}\n initial={{ opacity: 0.6, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0.6, scale: 0.95 }}\n transition={statusMorphTransition}\n className={cn(\n statusBadgeVariants({ color, size }),\n clickableClasses,\n className,\n )}\n {...motionProps(props)}\n >\n {!hideDot && (\n <span\n className={cn(\n 'shrink-0 rounded-pill',\n size === 'sm' ? 'h-ds-02b w-ds-02b' : 'h-[8px] w-[8px]',\n dotColor,\n )}\n aria-hidden=\"true\"\n />\n )}\n {displayLabel}\n {trailingIcon}\n </Tag>\n </AnimatePresence>\n )\n }\n\n // Status branch — derive styling from status (default: 'pending')\n const statusKey = status ?? 'pending'\n const displayLabel = label ?? (statusKey.charAt(0).toUpperCase() + statusKey.slice(1))\n const dotColor = dotColorMap[statusKey]\n\n return (\n <AnimatePresence mode=\"wait\">\n <Tag\n key={statusKey}\n ref={ref as any}\n {...(isClickable ? { type: 'button' as const, onClick } : {})}\n initial={{ opacity: 0.6 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0.6 }}\n transition={statusMorphTransition}\n className={cn(\n statusBadgeVariants({ status: statusKey, size }),\n clickableClasses,\n className,\n )}\n {...motionProps(props)}\n >\n {!hideDot && (\n <span\n className={cn(\n 'shrink-0 rounded-pill',\n size === 'sm' ? 'h-ds-02b w-ds-02b' : 'h-[8px] w-[8px]',\n dotColor,\n )}\n aria-hidden=\"true\"\n />\n )}\n {displayLabel}\n {trailingIcon}\n </Tag>\n </AnimatePresence>\n )\n },\n)\nStatusBadge.displayName = 'StatusBadge'\n\nexport { StatusBadge, statusBadgeVariants }\n"],"mappings":";;;;;;;;;;;;AAcA,IAAM,IAAsB,EAC1B,8DACA;CACE,UAAU;EACR,QAAQ;GACN,QAAQ;GACR,SAAS;GACT,UAAU;GACV,UAAU;GACV,WAAW;GACX,SAAS;GACT,eAAe;GACf,QAAQ;GACR,WAAW;GACX,OAAO;GACR;EACD,OAAO;GACL,SAAS;GACT,SAAS;GACT,OAAO;GACP,MAAM;GACN,SAAS;GACV;EACD,MAAM;GACJ,IAAI;GACJ,IAAI;GACL;EACF;CACD,iBAAiB,EACf,MAAM,MACP;CACF,CACF,EAEK,IAAsC;CAC1C,QAAQ;CACR,SAAS;CACT,UAAU;CACV,UAAU;CACV,WAAW;CACX,SAAS;CACT,eAAe;CACf,QAAQ;CACR,WAAW;CACX,OAAO;CACR,EAEK,IAAsC;CAC1C,SAAS;CACT,SAAS;CACT,OAAO;CACP,MAAM;CACN,SAAS;CACV,EAuBK,IAAwB;CAAE,UAAU;CAAK,MAAM;CAAoB,EAEnE,IAAc,EAAM,YACvB,EAAE,WAAQ,UAAO,SAAM,UAAO,aAAU,IAAO,YAAS,SAAM,cAAW,GAAG,KAAS,MAAQ;CAC5F,IAAM,IAAc,KAAW,MACzB,IAAM,IAAc,EAAO,SAAS,EAAO,MAC3C,IAAmB,IAAc,uDAAuD,KAAA,GAExF,IAAe,KAAQ,OAEzB,IACE,kBAAC,GAAD;EAAM,MAAM;EAAiB,MAAK;EAAK,WAAU;EAAqC,CAAA,GACtF,OAHF,kBAAC,GAAD;EAAc,MAAK;YAAM,EAAc,EAAK;EAAgB,CAAA;AAKhE,KAAI,KAAS,MAAM;EAEjB,IAAM,IAAe,KAAU,EAAM,OAAO,EAAE,CAAC,aAAa,GAAG,EAAM,MAAM,EAAE,EACvE,IAAW,EAAY;AAE7B,SACE,kBAAC,GAAD;GAAiB,MAAK;aACpB,kBAAC,GAAD;IAEO;IACL,GAAK,IAAc;KAAE,MAAM;KAAmB;KAAS,GAAG,EAAE;IAC5D,SAAS;KAAE,SAAS;KAAK,OAAO;KAAM;IACtC,SAAS;KAAE,SAAS;KAAG,OAAO;KAAG;IACjC,MAAM;KAAE,SAAS;KAAK,OAAO;KAAM;IACnC,YAAY;IACZ,WAAW,EACT,EAAoB;KAAE;KAAO;KAAM,CAAC,EACpC,GACA,EACD;IACD,GAAI,EAAY,EAAM;cAbxB;KAeG,CAAC,KACA,kBAAC,QAAD;MACE,WAAW,EACT,yBACA,MAAS,OAAO,sBAAsB,mBACtC,EACD;MACD,eAAY;MACZ,CAAA;KAEH;KACA;KACG;MA1BC,EA0BD;GACU,CAAA;;CAKtB,IAAM,IAAY,KAAU,WACtB,IAAe,KAAU,EAAU,OAAO,EAAE,CAAC,aAAa,GAAG,EAAU,MAAM,EAAE,EAC/E,IAAW,EAAY;AAE7B,QACE,kBAAC,GAAD;EAAiB,MAAK;YACpB,kBAAC,GAAD;GAEO;GACL,GAAK,IAAc;IAAE,MAAM;IAAmB;IAAS,GAAG,EAAE;GAC5D,SAAS,EAAE,SAAS,IAAK;GACzB,SAAS,EAAE,SAAS,GAAG;GACvB,MAAM,EAAE,SAAS,IAAK;GACtB,YAAY;GACZ,WAAW,EACT,EAAoB;IAAE,QAAQ;IAAW;IAAM,CAAC,EAChD,GACA,EACD;GACD,GAAI,EAAY,EAAM;aAbxB;IAeG,CAAC,KACA,kBAAC,QAAD;KACE,WAAW,EACT,yBACA,MAAS,OAAO,sBAAsB,mBACtC,EACD;KACD,eAAY;KACZ,CAAA;IAEH;IACA;IACG;KA1BC,EA0BD;EACU,CAAA;EAGvB;AACD,EAAY,cAAc"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { CommandGroup, CommandPaletteProps, FooterHint } from '../composed/command-palette';
|
|
3
|
+
import { IconInput } from '../ui/lib/icon-input';
|
|
3
4
|
import * as React from 'react';
|
|
4
5
|
export interface SearchResult {
|
|
5
6
|
id: string;
|
|
@@ -9,7 +10,7 @@ export interface SearchResult {
|
|
|
9
10
|
projectId?: string | null;
|
|
10
11
|
metadata?: Record<string, unknown>;
|
|
11
12
|
/** Custom icon for this result. Overrides the default entity-type icon. */
|
|
12
|
-
icon?:
|
|
13
|
+
icon?: IconInput;
|
|
13
14
|
/** Relevance score for sorting (higher = more relevant). */
|
|
14
15
|
rank?: number;
|
|
15
16
|
/** Keyboard shortcut hint to display on this result. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-command-palette.d.ts","sourceRoot":"","sources":["../../src/shell/app-command-palette.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAE,KAAK,YAAY,EAAoC,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"app-command-palette.d.ts","sourceRoot":"","sources":["../../src/shell/app-command-palette.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAE,KAAK,YAAY,EAAoC,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAE5I,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAQrD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,sBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5D,oDAAoD;IACpD,IAAI,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAA;IACnC,iHAAiH;IACjH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wCAAwC;IACxC,WAAW,CAAC,EAAE,YAAY,EAAE,CAAA;IAC5B,uDAAuD;IACvD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC;iEAC6D;IAC7D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAA;IAC9B;+DAC2D;IAC3D,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAA;IACxC,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;qFACiF;IACjF,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;IACrD;oEACgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;IAEzD,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,0BAA0B;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAA;IAC9C,8CAA8C;IAC9C,SAAS,CAAC,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAA;IAC5C,0BAA0B;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,iDAAiD;IACjD,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;CACnC;AAqCD,QAAA,MAAM,iBAAiB,4GAuJtB,CAAA;AAID,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-command-palette.js","names":[],"sources":["../../src/shell/app-command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * AppCommandPalette -- Application-level command palette wrapper.\n *\n * Props-driven: accepts navigation items, search callbacks, and user\n * info instead of reading from Zustand stores or Remix hooks.\n *\n * Depends on the CommandPalette shared component being available.\n */\nimport { IconFileText } from '@tabler/icons-react'\nimport * as React from 'react'\nimport { useCallback, useMemo } from 'react'\n\nimport { type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, type FooterHint } from '../composed/command-palette'\nimport { Icon } from '../ui/icon'\nimport { cn } from '../ui/lib/utils'\nimport { useCommandRegistry } from './command-registry'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface SearchResult {\n id: string\n title: string\n snippet?: string\n entityType: string\n projectId?: string | null\n metadata?: Record<string, unknown>\n /** Custom icon for this result. Overrides the default entity-type icon. */\n icon?: React.ReactNode\n /** Relevance score for sorting (higher = more relevant). */\n rank?: number\n /** Keyboard shortcut hint to display on this result. */\n shortcut?: string\n /** Navigation href. Used as fallback when onSearchResultSelect is not provided. */\n href?: string\n}\n\n/** A group of search results with a label. */\nexport interface SearchResultGroup {\n label: string\n results: SearchResult[]\n}\n\nexport interface AppCommandPaletteUser {\n name: string\n role?: string\n}\n\nexport interface AppCommandPaletteProps\n extends Omit<React.ComponentPropsWithRef<'div'>, 'onSearch'> {\n /** Current user (used to determine admin access) */\n user?: AppCommandPaletteUser | null\n /** When true, shows admin command groups regardless of user.role. Takes precedence over role-based detection. */\n isAdmin?: boolean\n /** Additional command groups to show */\n extraGroups?: CommandGroup[]\n /** Called when the user selects a navigation target */\n onNavigate?: (path: string) => void\n /** Called when the search input changes (for server-side search) */\n onSearch?: (query: string) => void\n /** Flat search results (displayed in a single \"Search Results\" group).\n * For grouped results, use `searchResultGroups` instead. */\n searchResults?: SearchResult[]\n /** Grouped search results — displayed as multiple labeled sections.\n * Takes precedence over `searchResults` when provided. */\n searchResultGroups?: SearchResultGroup[]\n /** Whether a search is currently in progress */\n isSearching?: boolean\n /** Called when the user selects a search result. When provided, the component\n * does NOT perform internal navigation — the consumer owns routing entirely. */\n onSearchResultSelect?: (result: SearchResult) => void\n /** Custom label for the search results group. Overrides \"Search Results\" / \"Searching...\".\n * Can be a string or a function receiving the result count. */\n searchResultsLabel?: string | ((count: number) => string)\n // -- Pass-through CommandPalette props --\n /** Controlled open state. */\n open?: boolean\n /** Default open state. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n /** Keybinding(s) to toggle. Pass `false` to disable. Default: 'mod+k'. */\n keybinding?: CommandPaletteProps['keybinding']\n /** Max height of results. Default '320px'. */\n maxHeight?: CommandPaletteProps['maxHeight']\n /** Custom empty state. */\n emptyState?: React.ReactNode\n /** Custom footer hints. Pass `false` to hide. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Constants\n// -----------------------------------------------------------------------\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\n/** Convert a SearchResult into a CommandItem. */\nfunction searchResultToCommandItem(\n r: SearchResult,\n onSearchResultSelect: ((result: SearchResult) => void) | undefined,\n nav: (to: string) => void,\n): CommandItem {\n return {\n id: `search-${r.entityType}-${r.id}`,\n label: r.title,\n filterValue: r.title,\n description: r.snippet,\n icon: r.icon ?? <Icon icon={IconFileText} />,\n shortcut: r.shortcut,\n onSelect: () => {\n if (onSearchResultSelect) {\n onSearchResultSelect(r)\n } else if (r.href) {\n nav(r.href)\n }\n },\n }\n}\n\n// -----------------------------------------------------------------------\n// AppCommandPalette\n// -----------------------------------------------------------------------\n\nconst AppCommandPalette = React.forwardRef<HTMLDivElement, AppCommandPaletteProps>(\n function AppCommandPalette(\n {\n user,\n isAdmin: isAdminProp,\n extraGroups = [],\n onNavigate,\n onSearch,\n searchResults = [],\n searchResultGroups,\n isSearching = false,\n onSearchResultSelect,\n searchResultsLabel,\n open,\n defaultOpen,\n onOpenChange,\n keybinding,\n maxHeight,\n emptyState,\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n const isAdmin =\n isAdminProp ?? (user?.role === 'Admin' || user?.role === 'SuperAdmin')\n\n const registry = useCommandRegistry()\n\n const nav = useCallback(\n (to: string) => {\n onNavigate?.(to)\n },\n [onNavigate],\n )\n\n // -- Static groups ---------------------------------------------------\n\n const pagesGroup: CommandGroup = useMemo(\n () => ({\n label: 'Pages',\n items: registry\n ? registry.pages.map((p) => ({\n id: p.id,\n label: p.label,\n icon: p.icon,\n keywords: p.keywords,\n onSelect: () => nav(p.path),\n }))\n : [], // Consumer provides pages via CommandRegistryProvider\n }),\n [nav, registry],\n )\n\n const adminGroup: CommandGroup = useMemo(\n () => ({\n label: 'Admin',\n items: registry\n ? registry.adminPages.map((p) => ({\n id: p.id,\n label: p.label,\n icon: p.icon,\n keywords: p.keywords,\n onSelect: () => nav(p.path),\n }))\n : [], // Consumer provides admin pages via CommandRegistryProvider\n }),\n [nav, registry],\n )\n\n // -- Dynamic search results groups ------------------------------------\n\n const searchGroups: CommandGroup[] = useMemo(() => {\n // Grouped results take precedence (#2)\n if (searchResultGroups && searchResultGroups.length > 0) {\n return searchResultGroups.map((group) => {\n // Sort by rank if provided\n const sorted = group.results.some(r => r.rank != null)\n ? [...group.results].sort((a, b) => (b.rank ?? 0) - (a.rank ?? 0))\n : group.results\n\n return {\n label: group.label,\n items: sorted.map(r => searchResultToCommandItem(r, onSearchResultSelect, nav)),\n }\n })\n }\n\n // Flat results (legacy behavior)\n if (searchResults.length === 0) return []\n\n // Sort by rank if any result has one\n const sorted = searchResults.some(r => r.rank != null)\n ? [...searchResults].sort((a, b) => (b.rank ?? 0) - (a.rank ?? 0))\n : searchResults\n\n const items = sorted.map(r => searchResultToCommandItem(r, onSearchResultSelect, nav))\n\n // Resolve the label (#10)\n let label: string\n if (searchResultsLabel) {\n label = typeof searchResultsLabel === 'function'\n ? searchResultsLabel(items.length)\n : searchResultsLabel\n } else {\n label = isSearching ? 'Searching...' : 'Search Results'\n }\n\n return [{ label, items }]\n }, [searchResults, searchResultGroups, isSearching, nav, onSearchResultSelect, searchResultsLabel])\n\n // -- Assemble groups -------------------------------------------------\n\n const groups: CommandGroup[] = useMemo(() => {\n const g: CommandGroup[] = []\n g.push(...searchGroups)\n g.push(pagesGroup)\n if (isAdmin) g.push(adminGroup)\n g.push(...extraGroups)\n return g\n }, [searchGroups, pagesGroup, isAdmin, adminGroup, extraGroups])\n\n // -- Handle search ---------------------------------------------------\n\n const handleSearch = useCallback(\n (query: string) => {\n onSearch?.(query)\n },\n [onSearch],\n )\n\n return (\n <CommandPalette\n ref={ref}\n groups={groups}\n placeholder=\"Search or jump to...\"\n onSearch={handleSearch}\n emptyMessage=\"No results found. Try a different search term.\"\n open={open}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n keybinding={keybinding}\n maxHeight={maxHeight}\n emptyState={emptyState}\n footerHints={footerHints}\n className={cn(className)}\n {...props}\n />\n )\n },\n)\n\nAppCommandPalette.displayName = 'AppCommandPalette'\n\nexport { AppCommandPalette }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-command-palette.js","names":[],"sources":["../../src/shell/app-command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * AppCommandPalette -- Application-level command palette wrapper.\n *\n * Props-driven: accepts navigation items, search callbacks, and user\n * info instead of reading from Zustand stores or Remix hooks.\n *\n * Depends on the CommandPalette shared component being available.\n */\nimport { IconFileText } from '@tabler/icons-react'\nimport * as React from 'react'\nimport { useCallback, useMemo } from 'react'\n\nimport { type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, type FooterHint } from '../composed/command-palette'\nimport { Icon } from '../ui/icon'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { cn } from '../ui/lib/utils'\nimport { useCommandRegistry } from './command-registry'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface SearchResult {\n id: string\n title: string\n snippet?: string\n entityType: string\n projectId?: string | null\n metadata?: Record<string, unknown>\n /** Custom icon for this result. Overrides the default entity-type icon. */\n icon?: IconInput\n /** Relevance score for sorting (higher = more relevant). */\n rank?: number\n /** Keyboard shortcut hint to display on this result. */\n shortcut?: string\n /** Navigation href. Used as fallback when onSearchResultSelect is not provided. */\n href?: string\n}\n\n/** A group of search results with a label. */\nexport interface SearchResultGroup {\n label: string\n results: SearchResult[]\n}\n\nexport interface AppCommandPaletteUser {\n name: string\n role?: string\n}\n\nexport interface AppCommandPaletteProps\n extends Omit<React.ComponentPropsWithRef<'div'>, 'onSearch'> {\n /** Current user (used to determine admin access) */\n user?: AppCommandPaletteUser | null\n /** When true, shows admin command groups regardless of user.role. Takes precedence over role-based detection. */\n isAdmin?: boolean\n /** Additional command groups to show */\n extraGroups?: CommandGroup[]\n /** Called when the user selects a navigation target */\n onNavigate?: (path: string) => void\n /** Called when the search input changes (for server-side search) */\n onSearch?: (query: string) => void\n /** Flat search results (displayed in a single \"Search Results\" group).\n * For grouped results, use `searchResultGroups` instead. */\n searchResults?: SearchResult[]\n /** Grouped search results — displayed as multiple labeled sections.\n * Takes precedence over `searchResults` when provided. */\n searchResultGroups?: SearchResultGroup[]\n /** Whether a search is currently in progress */\n isSearching?: boolean\n /** Called when the user selects a search result. When provided, the component\n * does NOT perform internal navigation — the consumer owns routing entirely. */\n onSearchResultSelect?: (result: SearchResult) => void\n /** Custom label for the search results group. Overrides \"Search Results\" / \"Searching...\".\n * Can be a string or a function receiving the result count. */\n searchResultsLabel?: string | ((count: number) => string)\n // -- Pass-through CommandPalette props --\n /** Controlled open state. */\n open?: boolean\n /** Default open state. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n /** Keybinding(s) to toggle. Pass `false` to disable. Default: 'mod+k'. */\n keybinding?: CommandPaletteProps['keybinding']\n /** Max height of results. Default '320px'. */\n maxHeight?: CommandPaletteProps['maxHeight']\n /** Custom empty state. */\n emptyState?: React.ReactNode\n /** Custom footer hints. Pass `false` to hide. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Constants\n// -----------------------------------------------------------------------\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\n/** Convert a SearchResult into a CommandItem. */\nfunction searchResultToCommandItem(\n r: SearchResult,\n onSearchResultSelect: ((result: SearchResult) => void) | undefined,\n nav: (to: string) => void,\n): CommandItem {\n return {\n id: `search-${r.entityType}-${r.id}`,\n label: r.title,\n filterValue: r.title,\n description: r.snippet,\n icon: r.icon ?? <Icon icon={IconFileText} />,\n shortcut: r.shortcut,\n onSelect: () => {\n if (onSearchResultSelect) {\n onSearchResultSelect(r)\n } else if (r.href) {\n nav(r.href)\n }\n },\n }\n}\n\n// -----------------------------------------------------------------------\n// AppCommandPalette\n// -----------------------------------------------------------------------\n\nconst AppCommandPalette = React.forwardRef<HTMLDivElement, AppCommandPaletteProps>(\n function AppCommandPalette(\n {\n user,\n isAdmin: isAdminProp,\n extraGroups = [],\n onNavigate,\n onSearch,\n searchResults = [],\n searchResultGroups,\n isSearching = false,\n onSearchResultSelect,\n searchResultsLabel,\n open,\n defaultOpen,\n onOpenChange,\n keybinding,\n maxHeight,\n emptyState,\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n const isAdmin =\n isAdminProp ?? (user?.role === 'Admin' || user?.role === 'SuperAdmin')\n\n const registry = useCommandRegistry()\n\n const nav = useCallback(\n (to: string) => {\n onNavigate?.(to)\n },\n [onNavigate],\n )\n\n // -- Static groups ---------------------------------------------------\n\n const pagesGroup: CommandGroup = useMemo(\n () => ({\n label: 'Pages',\n items: registry\n ? registry.pages.map((p) => ({\n id: p.id,\n label: p.label,\n icon: p.icon,\n keywords: p.keywords,\n onSelect: () => nav(p.path),\n }))\n : [], // Consumer provides pages via CommandRegistryProvider\n }),\n [nav, registry],\n )\n\n const adminGroup: CommandGroup = useMemo(\n () => ({\n label: 'Admin',\n items: registry\n ? registry.adminPages.map((p) => ({\n id: p.id,\n label: p.label,\n icon: p.icon,\n keywords: p.keywords,\n onSelect: () => nav(p.path),\n }))\n : [], // Consumer provides admin pages via CommandRegistryProvider\n }),\n [nav, registry],\n )\n\n // -- Dynamic search results groups ------------------------------------\n\n const searchGroups: CommandGroup[] = useMemo(() => {\n // Grouped results take precedence (#2)\n if (searchResultGroups && searchResultGroups.length > 0) {\n return searchResultGroups.map((group) => {\n // Sort by rank if provided\n const sorted = group.results.some(r => r.rank != null)\n ? [...group.results].sort((a, b) => (b.rank ?? 0) - (a.rank ?? 0))\n : group.results\n\n return {\n label: group.label,\n items: sorted.map(r => searchResultToCommandItem(r, onSearchResultSelect, nav)),\n }\n })\n }\n\n // Flat results (legacy behavior)\n if (searchResults.length === 0) return []\n\n // Sort by rank if any result has one\n const sorted = searchResults.some(r => r.rank != null)\n ? [...searchResults].sort((a, b) => (b.rank ?? 0) - (a.rank ?? 0))\n : searchResults\n\n const items = sorted.map(r => searchResultToCommandItem(r, onSearchResultSelect, nav))\n\n // Resolve the label (#10)\n let label: string\n if (searchResultsLabel) {\n label = typeof searchResultsLabel === 'function'\n ? searchResultsLabel(items.length)\n : searchResultsLabel\n } else {\n label = isSearching ? 'Searching...' : 'Search Results'\n }\n\n return [{ label, items }]\n }, [searchResults, searchResultGroups, isSearching, nav, onSearchResultSelect, searchResultsLabel])\n\n // -- Assemble groups -------------------------------------------------\n\n const groups: CommandGroup[] = useMemo(() => {\n const g: CommandGroup[] = []\n g.push(...searchGroups)\n g.push(pagesGroup)\n if (isAdmin) g.push(adminGroup)\n g.push(...extraGroups)\n return g\n }, [searchGroups, pagesGroup, isAdmin, adminGroup, extraGroups])\n\n // -- Handle search ---------------------------------------------------\n\n const handleSearch = useCallback(\n (query: string) => {\n onSearch?.(query)\n },\n [onSearch],\n )\n\n return (\n <CommandPalette\n ref={ref}\n groups={groups}\n placeholder=\"Search or jump to...\"\n onSearch={handleSearch}\n emptyMessage=\"No results found. Try a different search term.\"\n open={open}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n keybinding={keybinding}\n maxHeight={maxHeight}\n emptyState={emptyState}\n footerHints={footerHints}\n className={cn(className)}\n {...props}\n />\n )\n },\n)\n\nAppCommandPalette.displayName = 'AppCommandPalette'\n\nexport { AppCommandPalette }\n"],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { IconInput } from '../ui/lib/icon-input';
|
|
2
3
|
import * as React from 'react';
|
|
3
4
|
export interface BottomNavItem {
|
|
4
5
|
title: string;
|
|
5
6
|
href: string;
|
|
6
|
-
|
|
7
|
+
/** Icon for this nav item. Accepts any `IconInput`. */
|
|
8
|
+
icon: IconInput;
|
|
7
9
|
/** When true, the route matches only when the path is exactly equal */
|
|
8
10
|
exact?: boolean;
|
|
9
11
|
/** Notification badge count. 0 or undefined = hidden, 1–99 = shown, >99 = "99+" */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navbar.d.ts","sourceRoot":"","sources":["../../src/shell/bottom-navbar.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"bottom-navbar.d.ts","sourceRoot":"","sources":["../../src/shell/bottom-navbar.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAUrD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,IAAI,EAAE,SAAS,CAAA;IACf,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,iBACf,SAAQ,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC;IACzC,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,aAAa,EAAE,CAAA;IAC9B,yDAAyD;IACzD,SAAS,CAAC,EAAE,aAAa,EAAE,CAAA;IAC3B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4ED,QAAA,MAAM,YAAY,uFA6JjB,CAAA;AAGD,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -1,145 +1,153 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { IconProvider as e } from "../ui/icon-context.js";
|
|
3
|
+
import { springs as t } from "../ui/lib/motion.js";
|
|
4
|
+
import { cn as n } from "../ui/lib/utils.js";
|
|
5
|
+
import { Icon as r } from "../ui/icon.js";
|
|
6
|
+
import { t as i } from "../_chunks/normalize-icon.js";
|
|
7
|
+
import { n as a } from "../_chunks/link-context.js";
|
|
6
8
|
import "./link-context.js";
|
|
7
|
-
import * as
|
|
8
|
-
import { useCallback as
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { IconDots as
|
|
11
|
-
import { AnimatePresence as
|
|
9
|
+
import * as o from "react";
|
|
10
|
+
import { useCallback as s, useEffect as c, useRef as l, useState as u } from "react";
|
|
11
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
12
|
+
import { IconDots as m, IconX as h } from "@tabler/icons-react";
|
|
13
|
+
import { AnimatePresence as g, motion as _, useReducedMotion as v } from "framer-motion";
|
|
12
14
|
//#region src/shell/bottom-navbar.tsx
|
|
13
|
-
function
|
|
15
|
+
function y({ count: e }) {
|
|
14
16
|
if (!e || e <= 0) return null;
|
|
15
|
-
let
|
|
16
|
-
return /* @__PURE__ */
|
|
17
|
+
let t = e > 99 ? "99+" : String(e), r = e >= 10;
|
|
18
|
+
return /* @__PURE__ */ f("span", {
|
|
17
19
|
"aria-label": `${e} notifications`,
|
|
18
|
-
className:
|
|
19
|
-
children:
|
|
20
|
+
className: 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", r ? "px-0.5" : ""),
|
|
21
|
+
children: t
|
|
20
22
|
});
|
|
21
23
|
}
|
|
22
|
-
function
|
|
23
|
-
let
|
|
24
|
-
return /* @__PURE__ */
|
|
25
|
-
whileTap:
|
|
26
|
-
transition:
|
|
24
|
+
function b({ item: r, isActive: o, onClick: s }) {
|
|
25
|
+
let c = a(), l = v();
|
|
26
|
+
return /* @__PURE__ */ f(_.div, {
|
|
27
|
+
whileTap: l ? void 0 : { y: -2 },
|
|
28
|
+
transition: l ? { duration: 0 } : t.snappy,
|
|
27
29
|
className: "flex max-w-[70px] flex-1",
|
|
28
|
-
children: /* @__PURE__ */
|
|
29
|
-
href:
|
|
30
|
-
onClick:
|
|
31
|
-
"aria-label":
|
|
32
|
-
"aria-current":
|
|
33
|
-
className:
|
|
34
|
-
children: /* @__PURE__ */
|
|
30
|
+
children: /* @__PURE__ */ f(c, {
|
|
31
|
+
href: r.href,
|
|
32
|
+
onClick: s,
|
|
33
|
+
"aria-label": r.title,
|
|
34
|
+
"aria-current": o ? "page" : void 0,
|
|
35
|
+
className: n("flex h-16 w-full cursor-pointer flex-col items-center gap-ds-02 p-ds-02 pt-0 text-ds-sm transition-colors duration-fast-02 ease-productive-standard", o ? "font-semibold text-accent-11" : "text-surface-fg-subtle"),
|
|
36
|
+
children: /* @__PURE__ */ p("div", {
|
|
35
37
|
className: "relative flex w-full flex-col items-center gap-ds-02",
|
|
36
38
|
children: [
|
|
37
|
-
|
|
39
|
+
o && /* @__PURE__ */ f(_.div, {
|
|
38
40
|
layoutId: "bottom-nav-indicator",
|
|
39
41
|
className: "absolute top-0 h-[3px] w-full rounded-b-control-inner bg-accent-9 p-0",
|
|
40
42
|
"aria-hidden": "true",
|
|
41
|
-
transition:
|
|
43
|
+
transition: l ? { duration: 0 } : t.snappy
|
|
42
44
|
}),
|
|
43
|
-
/* @__PURE__ */
|
|
45
|
+
/* @__PURE__ */ p("div", {
|
|
44
46
|
className: "relative p-ds-03",
|
|
45
|
-
children: [/* @__PURE__ */
|
|
47
|
+
children: [/* @__PURE__ */ f("span", {
|
|
46
48
|
className: "[&>svg]:h-ico-md [&>svg]:w-ico-md",
|
|
47
49
|
"aria-hidden": "true",
|
|
48
|
-
children:
|
|
49
|
-
|
|
50
|
+
children: /* @__PURE__ */ f(e, {
|
|
51
|
+
size: "md",
|
|
52
|
+
children: i(r.icon)
|
|
53
|
+
})
|
|
54
|
+
}), r.badge != null && /* @__PURE__ */ f(y, { count: r.badge })]
|
|
50
55
|
}),
|
|
51
|
-
/* @__PURE__ */
|
|
56
|
+
/* @__PURE__ */ f("span", {
|
|
52
57
|
className: "text-center",
|
|
53
|
-
children:
|
|
58
|
+
children: r.title
|
|
54
59
|
})
|
|
55
60
|
]
|
|
56
61
|
})
|
|
57
62
|
})
|
|
58
63
|
});
|
|
59
64
|
}
|
|
60
|
-
var
|
|
61
|
-
let
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}, [
|
|
65
|
-
let
|
|
66
|
-
return /* @__PURE__ */ d
|
|
65
|
+
var x = o.forwardRef(({ currentPath: o = "/", user: y, primaryItems: x = [], moreItems: S = [], className: C, ...w }, T) => {
|
|
66
|
+
let E = a(), D = v(), [O, k] = u(!1), A = l(null), j = s(() => k(!1), []);
|
|
67
|
+
c(() => {
|
|
68
|
+
O && A.current && A.current.querySelector("a, button")?.focus();
|
|
69
|
+
}, [O]);
|
|
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", {
|
|
67
72
|
className: "fixed inset-0 z-overlay md:hidden",
|
|
68
|
-
onClick: () =>
|
|
69
|
-
children: [/* @__PURE__ */
|
|
70
|
-
ref:
|
|
73
|
+
onClick: () => k(!1),
|
|
74
|
+
children: [/* @__PURE__ */ f("div", { className: "absolute inset-0 bg-overlay" }), /* @__PURE__ */ p(_.div, {
|
|
75
|
+
ref: A,
|
|
71
76
|
role: "dialog",
|
|
72
77
|
"aria-label": "More navigation",
|
|
73
78
|
initial: { y: "100%" },
|
|
74
79
|
animate: { y: 0 },
|
|
75
80
|
exit: { y: "100%" },
|
|
76
|
-
transition:
|
|
81
|
+
transition: D ? { duration: 0 } : t.smooth,
|
|
77
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",
|
|
78
83
|
onClick: (e) => e.stopPropagation(),
|
|
79
84
|
onKeyDown: (e) => {
|
|
80
|
-
e.stopPropagation(), e.key === "Escape" &&
|
|
85
|
+
e.stopPropagation(), e.key === "Escape" && j();
|
|
81
86
|
},
|
|
82
|
-
children: [/* @__PURE__ */
|
|
87
|
+
children: [/* @__PURE__ */ p("div", {
|
|
83
88
|
className: "mb-ds-04 flex items-center justify-between",
|
|
84
|
-
children: [/* @__PURE__ */
|
|
89
|
+
children: [/* @__PURE__ */ f("span", {
|
|
85
90
|
className: "text-ds-md font-semibold text-surface-fg",
|
|
86
91
|
children: "More"
|
|
87
|
-
}), /* @__PURE__ */
|
|
88
|
-
onClick: () =>
|
|
92
|
+
}), /* @__PURE__ */ f("button", {
|
|
93
|
+
onClick: () => k(!1),
|
|
89
94
|
"aria-label": "Close more menu",
|
|
90
95
|
className: "flex h-ds-sm w-ds-sm items-center justify-center rounded-pill hover:bg-surface-raised-hover",
|
|
91
|
-
children: /* @__PURE__ */
|
|
92
|
-
icon:
|
|
96
|
+
children: /* @__PURE__ */ f(r, {
|
|
97
|
+
icon: h,
|
|
93
98
|
size: "sm",
|
|
94
99
|
className: "text-surface-fg-muted"
|
|
95
100
|
})
|
|
96
101
|
})]
|
|
97
|
-
}), /* @__PURE__ */
|
|
102
|
+
}), /* @__PURE__ */ f("div", {
|
|
98
103
|
className: "grid grid-cols-4 gap-ds-03",
|
|
99
|
-
children:
|
|
100
|
-
href:
|
|
101
|
-
onClick: () =>
|
|
102
|
-
className:
|
|
103
|
-
children: [/* @__PURE__ */
|
|
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-ds-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", {
|
|
104
109
|
className: "[&>svg]:h-ico-md [&>svg]:w-ico-md",
|
|
105
|
-
children: e
|
|
106
|
-
|
|
110
|
+
children: /* @__PURE__ */ f(e, {
|
|
111
|
+
size: "md",
|
|
112
|
+
children: i(t.icon)
|
|
113
|
+
})
|
|
114
|
+
}), /* @__PURE__ */ f("span", {
|
|
107
115
|
className: "text-center",
|
|
108
|
-
children:
|
|
116
|
+
children: t.title
|
|
109
117
|
})]
|
|
110
|
-
},
|
|
118
|
+
}, t.href))
|
|
111
119
|
})]
|
|
112
120
|
})]
|
|
113
|
-
}) }), /* @__PURE__ */
|
|
114
|
-
...
|
|
115
|
-
ref:
|
|
121
|
+
}) }), /* @__PURE__ */ p("nav", {
|
|
122
|
+
...w,
|
|
123
|
+
ref: T,
|
|
116
124
|
"aria-label": "Mobile navigation",
|
|
117
|
-
className:
|
|
118
|
-
children: [
|
|
125
|
+
className: 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-raised px-ds-05 pb-safe pt-0 md:hidden", C),
|
|
126
|
+
children: [x.map((e) => /* @__PURE__ */ f(b, {
|
|
119
127
|
item: e,
|
|
120
|
-
isActive:
|
|
121
|
-
}, e.href)),
|
|
128
|
+
isActive: M(e.href, e.exact)
|
|
129
|
+
}, e.href)), S.length > 0 && /* @__PURE__ */ f(_.button, {
|
|
122
130
|
type: "button",
|
|
123
|
-
onClick: () =>
|
|
131
|
+
onClick: () => k(!O),
|
|
124
132
|
"aria-label": "More navigation options",
|
|
125
|
-
"aria-expanded":
|
|
126
|
-
whileTap:
|
|
127
|
-
transition:
|
|
128
|
-
className:
|
|
129
|
-
children: /* @__PURE__ */
|
|
133
|
+
"aria-expanded": O,
|
|
134
|
+
whileTap: D ? void 0 : { y: -2 },
|
|
135
|
+
transition: D ? { duration: 0 } : t.snappy,
|
|
136
|
+
className: n("flex h-16 max-w-[70px] flex-1 cursor-pointer flex-col items-center gap-ds-02 p-ds-02 pt-0 text-ds-sm", O || N ? "font-semibold text-accent-11" : "text-surface-fg-subtle"),
|
|
137
|
+
children: /* @__PURE__ */ p("div", {
|
|
130
138
|
className: "relative flex w-full flex-col items-center gap-ds-02",
|
|
131
139
|
children: [
|
|
132
|
-
(
|
|
140
|
+
(O || N) && /* @__PURE__ */ f(_.div, {
|
|
133
141
|
layoutId: "bottom-nav-indicator",
|
|
134
142
|
className: "absolute top-0 h-[3px] w-full rounded-b-control-inner bg-accent-9 p-0",
|
|
135
143
|
"aria-hidden": "true",
|
|
136
|
-
transition:
|
|
144
|
+
transition: D ? { duration: 0 } : t.snappy
|
|
137
145
|
}),
|
|
138
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ f("div", {
|
|
139
147
|
className: "p-ds-03",
|
|
140
|
-
children: /* @__PURE__ */
|
|
148
|
+
children: /* @__PURE__ */ f(r, { icon: m })
|
|
141
149
|
}),
|
|
142
|
-
/* @__PURE__ */
|
|
150
|
+
/* @__PURE__ */ f("span", {
|
|
143
151
|
className: "text-center",
|
|
144
152
|
children: "More"
|
|
145
153
|
})
|
|
@@ -148,6 +156,6 @@ var y = i.forwardRef(({ currentPath: i = "/", user: _, primaryItems: y = [], mor
|
|
|
148
156
|
})]
|
|
149
157
|
})] });
|
|
150
158
|
});
|
|
151
|
-
|
|
159
|
+
x.displayName = "BottomNavbar";
|
|
152
160
|
//#endregion
|
|
153
|
-
export {
|
|
161
|
+
export { x as BottomNavbar };
|