@espressif/dashboard-ui-components 1.5.0 → 1.7.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/.claude/rules/dashboard-ui-consumption.md +31 -0
- package/.cursor/rules/dashboard-ui-consumption.mdc +31 -0
- package/CHANGELOG.md +167 -0
- package/README.md +1 -0
- package/dist/{chunk-ZEQNTNMW.js → chunk-3PO2SF7T.js} +57 -24
- package/dist/{chunk-6RJAKSPV.js → chunk-AM47GLNJ.js} +15 -11
- package/dist/{chunk-45DCL46L.js → chunk-UA4DS3KA.js} +1 -1
- package/dist/{chunk-X7LDLZBT.js → chunk-WS6QCUCT.js} +736 -54
- package/dist/{chunk-WR54R7J6.js → chunk-ZJ6UJR2D.js} +2 -2
- package/dist/common/index.js +4 -4
- package/dist/components/index.d.ts +134 -8
- package/dist/components/index.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/layouts/index.js +3 -3
- package/package.json +1 -1
- package/src/styles/colors.css +3 -2
|
@@ -110,6 +110,37 @@ Things agents get wrong about it:
|
|
|
110
110
|
full page reload.
|
|
111
111
|
- No `prose` wrapper or spacing utilities are needed; it owns its own vertical rhythm.
|
|
112
112
|
|
|
113
|
+
## Editing code and JSON
|
|
114
|
+
|
|
115
|
+
`CodeEditor` (from `/components`) is the editable counterpart of `Code`: a form field
|
|
116
|
+
with syntax highlighting. Use it instead of `Textarea` for JSON payloads, policies or
|
|
117
|
+
templates; use `Code` for read-only display.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { CodeEditor } from '@espressif/dashboard-ui-components/components'
|
|
121
|
+
|
|
122
|
+
<CodeEditor
|
|
123
|
+
{...field} // react-hook-form: native onChange + ref to the <textarea>
|
|
124
|
+
lang="json" // "text" for base64 / opaque data
|
|
125
|
+
theme={dark ? 'dark' : 'light'}
|
|
126
|
+
label="Payload"
|
|
127
|
+
errorContent={fieldState.error?.message}
|
|
128
|
+
onFormatError={(e) => setFormatError(String(e))}
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Things agents get wrong about it:
|
|
133
|
+
|
|
134
|
+
- `onChange` receives the native change event, like `Textarea` — there is no `onValueChange`.
|
|
135
|
+
- It does **not** validate. The built-in Format button (JSON only) pretty-prints and
|
|
136
|
+
reports invalid JSON to `onFormatError`; schema rules (zod etc.) stay in the app.
|
|
137
|
+
Pass `formatter` for other languages; do not reimplement Format in `headerActions`.
|
|
138
|
+
- Esc, then Tab, moves focus out (Tab otherwise indents). Inside a `Sheet` or `Dialog`,
|
|
139
|
+
Esc also reaches the overlay's own Escape handler and closes it; guard with
|
|
140
|
+
`onEscapeKeyDown={(e) => { if ((e.target as Element).closest('[data-slot="code-editor"]')) e.preventDefault() }}`
|
|
141
|
+
if that matters.
|
|
142
|
+
- `className` / `style` style the editor box, not the `<textarea>`.
|
|
143
|
+
|
|
113
144
|
## Bundle size and tooling (what agents should assume)
|
|
114
145
|
|
|
115
146
|
- The published library is **pre-bundled ESM** (tsup). Consumers receive **large `dist` chunks**, not one file per source component.
|
|
@@ -107,6 +107,37 @@ Things agents get wrong about it:
|
|
|
107
107
|
full page reload.
|
|
108
108
|
- No `prose` wrapper or spacing utilities are needed; it owns its own vertical rhythm.
|
|
109
109
|
|
|
110
|
+
## Editing code and JSON
|
|
111
|
+
|
|
112
|
+
`CodeEditor` (from `/components`) is the editable counterpart of `Code`: a form field
|
|
113
|
+
with syntax highlighting. Use it instead of `Textarea` for JSON payloads, policies or
|
|
114
|
+
templates; use `Code` for read-only display.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { CodeEditor } from '@espressif/dashboard-ui-components/components'
|
|
118
|
+
|
|
119
|
+
<CodeEditor
|
|
120
|
+
{...field} // react-hook-form: native onChange + ref to the <textarea>
|
|
121
|
+
lang="json" // "text" for base64 / opaque data
|
|
122
|
+
theme={dark ? 'dark' : 'light'}
|
|
123
|
+
label="Payload"
|
|
124
|
+
errorContent={fieldState.error?.message}
|
|
125
|
+
onFormatError={(e) => setFormatError(String(e))}
|
|
126
|
+
/>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Things agents get wrong about it:
|
|
130
|
+
|
|
131
|
+
- `onChange` receives the native change event, like `Textarea` — there is no `onValueChange`.
|
|
132
|
+
- It does **not** validate. The built-in Format button (JSON only) pretty-prints and
|
|
133
|
+
reports invalid JSON to `onFormatError`; schema rules (zod etc.) stay in the app.
|
|
134
|
+
Pass `formatter` for other languages; do not reimplement Format in `headerActions`.
|
|
135
|
+
- Esc, then Tab, moves focus out (Tab otherwise indents). Inside a `Sheet` or `Dialog`,
|
|
136
|
+
Esc also reaches the overlay's own Escape handler and closes it; guard with
|
|
137
|
+
`onEscapeKeyDown={(e) => { if ((e.target as Element).closest('[data-slot="code-editor"]')) e.preventDefault() }}`
|
|
138
|
+
if that matters.
|
|
139
|
+
- `className` / `style` style the editor box, not the `<textarea>`.
|
|
140
|
+
|
|
110
141
|
## Bundle size and tooling (what agents should assume)
|
|
111
142
|
|
|
112
143
|
- The published library is **pre-bundled ESM** (tsup). Consumers receive **large `dist` chunks**, not one file per source component.
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,173 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres
|
|
5
5
|
to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [1.7.0] - 2026-10-06
|
|
8
|
+
|
|
9
|
+
A minor release adding per-item icons and colours to `OverflowBadgeList`
|
|
10
|
+
and element icons to `StatusBadge`, with fixes to the collapsed `Sidebar`
|
|
11
|
+
flyout menus and the `WorkspaceLayout` account menu. No breaking changes.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- **`OverflowBadgeList`** — per-item icons and colours. `items` now also
|
|
15
|
+
accepts `{ id?, label, icon?, color? }` objects (exported as
|
|
16
|
+
`OverflowBadgeListItem`), which can be mixed with plain strings. Each
|
|
17
|
+
object item renders its own `icon` and uses its own `color` in place of
|
|
18
|
+
`badgeColor`, so a list can show, for example, a brand icon per
|
|
19
|
+
integration and grey out inactive entries. Plain-string items behave as
|
|
20
|
+
before: the list-level `icon` appears on the first badge only.
|
|
21
|
+
- **`StatusBadge`** — `icon` also accepts a pre-built element (such as a
|
|
22
|
+
custom SVG brand icon) in addition to a Lucide component. Elements are
|
|
23
|
+
rendered as-is, so the caller sets their size. The type is exported as
|
|
24
|
+
`StatusBadgeIcon`. No breaking changes.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- **`IconTextActionCard`, `SimpleClickableCard`, `SimpleInfoCard`** — a
|
|
28
|
+
`title` passed as a ReactNode now gets the same title typography (size and
|
|
29
|
+
weight for the card `size`) as a string title, instead of inheriting the
|
|
30
|
+
surrounding text style. It is still wrapped in a `div`, so block content
|
|
31
|
+
stays valid. Elements inside the title that set their own font size or
|
|
32
|
+
weight are unaffected; plain text inside it becomes the title weight.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- **`StatusBadge` / `OverflowBadgeList`** — badges with an icon no longer
|
|
36
|
+
sit higher than badges without one.
|
|
37
|
+
- **`Sidebar` / `WorkspaceLayout`** — collapsed sidebar flyout menus:
|
|
38
|
+
- Choosing an item no longer brings back the group's label tooltip.
|
|
39
|
+
Closing the flyout with Escape or the keyboard still returns focus to
|
|
40
|
+
the group icon.
|
|
41
|
+
- Clicking anywhere on a row now navigates and closes the flyout.
|
|
42
|
+
Previously, with a router `linkComponent`, clicking the empty part of a
|
|
43
|
+
row navigated but left the flyout open, and clicking the row's edge
|
|
44
|
+
closed it without navigating.
|
|
45
|
+
- Choosing an item with Enter or Space now navigates to it. Previously the
|
|
46
|
+
flyout closed without navigating.
|
|
47
|
+
- **`WorkspaceLayout`** — clicking the profile card in the account menu
|
|
48
|
+
(when `onProfileCardClick` is set) now closes the menu after the callback
|
|
49
|
+
runs. The card also highlights on hover like the other menu rows and can
|
|
50
|
+
be reached with the arrow keys and chosen with Enter or Space.
|
|
51
|
+
|
|
52
|
+
### Internal
|
|
53
|
+
Nothing in this section affects the published package.
|
|
54
|
+
|
|
55
|
+
- Demo: the landing page's right panel now plays a looping, silent showreel
|
|
56
|
+
of the library's components, rendered from the real components by
|
|
57
|
+
`demo/video` (`npm run video:beats` / `npm run video:render`).
|
|
58
|
+
- Demo: the `OverflowBadgeList` page gains a per-item icons example, and the
|
|
59
|
+
`WorkspaceLayout` page wires `onProfileCardClick` / `onLogoutClick` and
|
|
60
|
+
documents `onProfileCardClick`.
|
|
61
|
+
- Tests for `IconTextActionCard`, `OverflowBadgeList`, `Sidebar` and the
|
|
62
|
+
`WorkspaceLayout` account menu.
|
|
63
|
+
|
|
64
|
+
## [1.6.0] - 2026-09-25
|
|
65
|
+
|
|
66
|
+
A minor release adding an editable code field (`CodeEditor`), a warning
|
|
67
|
+
state to `StatusCardList`, fixed-value fields to `KeyValueManager`, and
|
|
68
|
+
rolling presets plus a clear action to `DateRangePicker`. Focus rings now
|
|
69
|
+
follow the primary colour, and a render loop in `DataTable` is fixed. No
|
|
70
|
+
breaking changes.
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
- **`CodeEditor`** — an editable, syntax-highlighted code field. It has the
|
|
74
|
+
same header, file name, copy button and Shiki themes as `Code`, and works
|
|
75
|
+
in a form like `Textarea`: controlled or uncontrolled, native `onChange` /
|
|
76
|
+
`onBlur` / `name`, a ref to the `<textarea>`, so `{...field}` and
|
|
77
|
+
`{...register(name)}` from react-hook-form work unchanged (including
|
|
78
|
+
values written by `setValue` / `reset`). Carries `label`, `required`,
|
|
79
|
+
`hintContent`, `error`, `errorContent`, `disabled`, `readOnly` and
|
|
80
|
+
`placeholder`.
|
|
81
|
+
- Tab indents (every line of a multi-line selection), Shift+Tab outdents,
|
|
82
|
+
Enter keeps the current indentation, and all three are undoable with
|
|
83
|
+
Cmd/Ctrl+Z. Press Esc, then Tab, to move focus out of the editor. Keys
|
|
84
|
+
pressed during IME composition are left alone.
|
|
85
|
+
- For `lang="json"` the header has a Format button that pretty-prints with
|
|
86
|
+
`tabSize` spaces (undoable, fires `onChange`). Invalid JSON is left
|
|
87
|
+
unchanged and passed to `onFormatError`. `formatter` supplies a
|
|
88
|
+
formatter for any language; `formatButton={false}` hides the button;
|
|
89
|
+
`formatLabel` sets its accessible name, and `copyLabel` sets the copy
|
|
90
|
+
button's. `headerActions` adds further
|
|
91
|
+
header controls.
|
|
92
|
+
- `hideHeader` removes the header. It is also left out automatically when
|
|
93
|
+
there is no `fileName`, no `headerActions`, and neither a copy nor a
|
|
94
|
+
format button.
|
|
95
|
+
- Other props: `lang` (default `"json"`; `"text"` for base64 or other
|
|
96
|
+
opaque data), `theme` / `themes`, `fileName`, `icon`, `copyButton`,
|
|
97
|
+
`minHeight` / `maxHeight` of the editing area, `wrap` (soft-wrap long
|
|
98
|
+
lines; off by default) and `tabSize` (default 2).
|
|
99
|
+
- Above `maxHighlightLength` characters (default 10 000) the editor shows
|
|
100
|
+
plain text, so typing in a large document stays responsive. Highlighting
|
|
101
|
+
one keystroke of a 64 KB JSON document takes about 64 ms on an Apple M4,
|
|
102
|
+
and a 10 KB one about 13 ms. Languages or themes outside the curated
|
|
103
|
+
Shiki bundle also render as plain text, with one console warning per
|
|
104
|
+
language.
|
|
105
|
+
- Text renders at 16px below the `md` breakpoint so iOS Safari does not
|
|
106
|
+
zoom on focus, and at 13px (like `Code`) from `md` up.
|
|
107
|
+
- **`DateRangePicker`** — rolling presets and a clear action:
|
|
108
|
+
- New presets `last-1-hour`, `last-24-hours`, `past-7-days` and
|
|
109
|
+
`past-30-days`. They end at the moment they are selected instead of
|
|
110
|
+
snapping to day boundaries, so `past-7-days` and `past-30-days` include
|
|
111
|
+
today (the existing `last-7-days` and `last-30-days` end yesterday at
|
|
112
|
+
23:59 and are unchanged). `ROLLING_PRESET_IDS` lists them, so a consumer
|
|
113
|
+
can recompute the range with `computeDateRange` when it refreshes data.
|
|
114
|
+
- New `clearable` prop. While a preset or custom range is selected, the
|
|
115
|
+
menu shows a "Clear" item that calls the new `onClear` callback and
|
|
116
|
+
closes the menu. `clearLabel` overrides its text (default `"Clear"`).
|
|
117
|
+
- Code with an exhaustive `switch` over `DateRangePickerPresetId` must
|
|
118
|
+
handle the four new IDs.
|
|
119
|
+
- **`KeyValueManager`** — two new `KeyValueManagerFieldMeta` options:
|
|
120
|
+
- `options` renders the field in the add popover as a select limited to
|
|
121
|
+
those values, and rejects any other value. Use it when the allowed values
|
|
122
|
+
are known up front, for example the header columns of an uploaded CSV.
|
|
123
|
+
- `regexFlags` is passed to the `RegExp` built from `regex`, so a pattern
|
|
124
|
+
can use Unicode property escapes such as `\p{L}` with `"u"`. Patterns
|
|
125
|
+
without flags behave as before.
|
|
126
|
+
- New label `selectPlaceholder` (default `"Select"`) for fields with
|
|
127
|
+
`options`.
|
|
128
|
+
- **`StatusCardList`** — new `"warning"` value for `StatusCardState`, for a
|
|
129
|
+
step that finished but only partly succeeded (for example, a bulk job where
|
|
130
|
+
some items failed). It uses the `warning` colour token for the card, avatar
|
|
131
|
+
and text, and a `TriangleAlert` end icon. Code with an exhaustive `switch`
|
|
132
|
+
over `StatusCardState` must handle the new value.
|
|
133
|
+
- **AI agent rules** — `.claude/rules/dashboard-ui-consumption.md` and
|
|
134
|
+
`.cursor/rules/dashboard-ui-consumption.mdc` gain an "Editing code and JSON"
|
|
135
|
+
section on `CodeEditor`: when to use it instead of `Textarea` / `Code`, the
|
|
136
|
+
react-hook-form wiring, and the usual mistakes (there is no `onValueChange`,
|
|
137
|
+
it does not validate, Esc inside a `Sheet` / `Dialog`).
|
|
138
|
+
|
|
139
|
+
### Changed
|
|
140
|
+
- **Focus ring colour** — `--color-ring` now defaults to `var(--color-primary)`
|
|
141
|
+
in light and dark mode instead of fixed blues (`#0053c2` / `#7cd9ff`).
|
|
142
|
+
Components that draw their focus ring with `ring-ring` (`Input`, `Select`,
|
|
143
|
+
`Textarea`, `SearchBox`, `AdvancedSearchBox`, `ToggleGroup`, `Tabs`,
|
|
144
|
+
`Switch`, `Checkbox`, `Dialog` and others) previously kept the blue ring in
|
|
145
|
+
apps that re-theme `primary`, while `Button` and the clickable cards already
|
|
146
|
+
used `ring-primary`, so focus rings in the same toolbar did not match.
|
|
147
|
+
- With the default theme, light mode's ring moves from `#0053c2` to the
|
|
148
|
+
primary `#0071e3`; dark mode is unchanged (both were `#7cd9ff`).
|
|
149
|
+
- Apps that want a ring distinct from primary can still set `--color-ring`.
|
|
150
|
+
- **`DateRangePicker`** — a picker without a `presets` prop shows every
|
|
151
|
+
preset, so its menu now also lists the four new rolling presets. They sit
|
|
152
|
+
among the trailing ranges, which run shortest to longest: "Last 1 hour" and
|
|
153
|
+
"Last 24 hours" come before "Last 1 day", and "Past 7 days" / "Past 30 days"
|
|
154
|
+
come just before "Last 7 days" / "Last 30 days". `PRESET_IDS` follows the
|
|
155
|
+
same order. Pass `presets` to keep the previous menu.
|
|
156
|
+
- **`Code`** — the header's copy button now has an accessible name and
|
|
157
|
+
tooltip (`aria-label` / `title` "Copy"); before, the icon-only button had
|
|
158
|
+
no name for screen readers. The header is now shared with `CodeEditor` and
|
|
159
|
+
is otherwise unchanged.
|
|
160
|
+
|
|
161
|
+
### Fixed
|
|
162
|
+
- **`DataTable`** — no longer triggers an extra internal re-render every time
|
|
163
|
+
`data` changes identity. TanStack Table resets the page index when `data`
|
|
164
|
+
changes unless pagination is manual, and each reset was a table-internal
|
|
165
|
+
state update. The page index here is always 0 (paging belongs to the
|
|
166
|
+
consumer through `pageIndex` / `onNextPage` / `onPrevPage`), so the reset
|
|
167
|
+
did nothing useful. With a consumer passing a fresh array on every render
|
|
168
|
+
(`data?.items ?? []`), those updates could pile up into React's "Maximum
|
|
169
|
+
update depth exceeded" under load, for example when switching to a
|
|
170
|
+
server-paginated table while the main thread was busy. The table now sets
|
|
171
|
+
`autoResetPageIndex: false` and memoizes its pagination state. Rows are
|
|
172
|
+
still capped at `pageSize`, so existing tables render the same.
|
|
173
|
+
|
|
7
174
|
## [1.5.0] - 2026-09-22
|
|
8
175
|
|
|
9
176
|
A minor release adding a combined date and time control.
|
package/README.md
CHANGED
|
@@ -455,6 +455,7 @@ version you have installed is the shipped type declarations:
|
|
|
455
455
|
| Alert | Alert banners (optionally dismissible) |
|
|
456
456
|
| Link | Styled anchor element — colour-tinted pill, or `variant="ghost"` for a bare inline link |
|
|
457
457
|
| Code | Syntax-highlighted code blocks |
|
|
458
|
+
| CodeEditor | Editable, syntax-highlighted code field (`Code` look, `Textarea` form behaviour), with Format (JSON) and Copy buttons |
|
|
458
459
|
| MarkdownContent | Renders a markdown string with library primitives (GFM, heading anchors; raw HTML is escaped, not parsed) |
|
|
459
460
|
| CopiableText / CopyButton | Copy-to-clipboard utilities |
|
|
460
461
|
| ProgressBar | Progress indicator |
|
|
@@ -3637,11 +3637,16 @@ function ItemIcon({
|
|
|
3637
3637
|
if (active) return /* @__PURE__ */ jsx(CircleDot, { className });
|
|
3638
3638
|
return /* @__PURE__ */ jsx(Circle, { className: cn("opacity-50", className) });
|
|
3639
3639
|
}
|
|
3640
|
+
function forwardRowClickToLink(e) {
|
|
3641
|
+
if (e.target !== e.currentTarget) return;
|
|
3642
|
+
e.currentTarget.firstElementChild?.click();
|
|
3643
|
+
}
|
|
3640
3644
|
function GroupMenuItems({
|
|
3641
3645
|
group,
|
|
3642
3646
|
isSelected,
|
|
3643
3647
|
linkComponent: LinkComponent,
|
|
3644
|
-
onItemClick
|
|
3648
|
+
onItemClick,
|
|
3649
|
+
onItemPointerDown
|
|
3645
3650
|
}) {
|
|
3646
3651
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3647
3652
|
/* @__PURE__ */ jsxs(
|
|
@@ -3662,10 +3667,21 @@ function GroupMenuItems({
|
|
|
3662
3667
|
/* @__PURE__ */ jsx(DropdownMenuSeparator2, {}),
|
|
3663
3668
|
group.items.map((item) => {
|
|
3664
3669
|
const active = isSelected(item.path);
|
|
3665
|
-
return /* @__PURE__ */ jsx(
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3670
|
+
return /* @__PURE__ */ jsx(
|
|
3671
|
+
DropdownMenuItem2,
|
|
3672
|
+
{
|
|
3673
|
+
className: active ? "bg-accent" : "",
|
|
3674
|
+
style: rowFontStyle,
|
|
3675
|
+
onPointerDown: onItemPointerDown,
|
|
3676
|
+
onClickCapture: onItemClick,
|
|
3677
|
+
onClick: forwardRowClickToLink,
|
|
3678
|
+
children: /* @__PURE__ */ jsxs(LinkComponent, { to: item.path, className: "flex items-center gap-2 cursor-pointer w-full", children: [
|
|
3679
|
+
/* @__PURE__ */ jsx(ItemIcon, { icon: item.icon, active }),
|
|
3680
|
+
/* @__PURE__ */ jsx("span", { className: active ? "font-semibold" : "font-medium", children: item.label })
|
|
3681
|
+
] })
|
|
3682
|
+
},
|
|
3683
|
+
item.id
|
|
3684
|
+
);
|
|
3669
3685
|
})
|
|
3670
3686
|
] });
|
|
3671
3687
|
}
|
|
@@ -3675,28 +3691,45 @@ function CollapsedSidebarGroup({
|
|
|
3675
3691
|
linkComponent: LinkComponent
|
|
3676
3692
|
}) {
|
|
3677
3693
|
const [open, setOpen] = useState(false);
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
children: /* @__PURE__ */ jsx(
|
|
3689
|
-
|
|
3694
|
+
const pickedWithPointer = useRef(false);
|
|
3695
|
+
return /* @__PURE__ */ jsx(SidebarGroup, { className: sidebarGroupClassName, children: /* @__PURE__ */ jsx(SidebarMenu, { className: "w-auto", children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
|
|
3696
|
+
DropdownMenu2,
|
|
3697
|
+
{
|
|
3698
|
+
open,
|
|
3699
|
+
onOpenChange: (next) => {
|
|
3700
|
+
if (next) pickedWithPointer.current = false;
|
|
3701
|
+
setOpen(next);
|
|
3702
|
+
},
|
|
3703
|
+
children: [
|
|
3704
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx(SidebarMenuButton, { size: "sm", tooltip: group.label, className: rowIconClass, children: /* @__PURE__ */ jsx(ItemIcon, { icon: group.icon }) }) }),
|
|
3705
|
+
/* @__PURE__ */ jsx(
|
|
3706
|
+
DropdownMenuContent2,
|
|
3690
3707
|
{
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3708
|
+
side: "right",
|
|
3709
|
+
align: "start",
|
|
3710
|
+
sideOffset: 8,
|
|
3711
|
+
className: "z-50 max-w-xs rounded-2xl shadow-lg will-change-[opacity,transform] py-1.5 overflow-visible select-none",
|
|
3712
|
+
style: { minWidth: 180 },
|
|
3713
|
+
onCloseAutoFocus: (e) => {
|
|
3714
|
+
if (pickedWithPointer.current) e.preventDefault();
|
|
3715
|
+
},
|
|
3716
|
+
children: /* @__PURE__ */ jsx(
|
|
3717
|
+
GroupMenuItems,
|
|
3718
|
+
{
|
|
3719
|
+
group,
|
|
3720
|
+
isSelected,
|
|
3721
|
+
linkComponent: LinkComponent,
|
|
3722
|
+
onItemClick: () => setOpen(false),
|
|
3723
|
+
onItemPointerDown: () => {
|
|
3724
|
+
pickedWithPointer.current = true;
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
)
|
|
3695
3728
|
}
|
|
3696
3729
|
)
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3730
|
+
]
|
|
3731
|
+
}
|
|
3732
|
+
) }) }) });
|
|
3700
3733
|
}
|
|
3701
3734
|
var groupHeaderClass = cn(
|
|
3702
3735
|
// No `flex-1`: this button is a column flex item, so growing made it take its
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FooterCard, MyAccountMenu, ProfileCard, AppLogo } from './chunk-
|
|
2
|
-
import { useSidebar, SidebarTrigger, SidebarProvider, Sidebar2, SidebarInset, parseTextMarkup, isPathPrefixOf, isSidebarGroup } from './chunk-
|
|
1
|
+
import { FooterCard, MyAccountMenu, ProfileCard, AppLogo } from './chunk-UA4DS3KA.js';
|
|
2
|
+
import { useSidebar, SidebarTrigger, DropdownMenuItem, SidebarProvider, Sidebar2, SidebarInset, parseTextMarkup, isPathPrefixOf, isSidebarGroup } from './chunk-3PO2SF7T.js';
|
|
3
3
|
import { Button, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator } from './chunk-OKB2WTX7.js';
|
|
4
4
|
import { cn } from './chunk-VU4CZ76T.js';
|
|
5
5
|
import { Menu, Palette, Check, Globe, LogOut } from 'lucide-react';
|
|
@@ -88,15 +88,19 @@ function AccountMenu({
|
|
|
88
88
|
groups.push({
|
|
89
89
|
id: "profile",
|
|
90
90
|
items: [
|
|
91
|
-
onProfileCardClick ?
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
91
|
+
onProfileCardClick ? (
|
|
92
|
+
// A menu item (not a plain button) so Radix closes the menu on select and
|
|
93
|
+
// includes the card in keyboard navigation. Negative margins cancel the
|
|
94
|
+
// custom-item wrapper's padding so the card keeps its position; they sit on
|
|
95
|
+
// an outer div because the hover highlight is sized from the item's wrapper.
|
|
96
|
+
/* @__PURE__ */ jsx("div", { className: "-mx-2.5 -my-1.5", children: /* @__PURE__ */ jsx(
|
|
97
|
+
DropdownMenuItem,
|
|
98
|
+
{
|
|
99
|
+
onSelect: onProfileCardClick,
|
|
100
|
+
className: "px-2.5 py-1.5 cursor-pointer *:flex-1 *:min-w-0",
|
|
101
|
+
children: profileCard
|
|
102
|
+
}
|
|
103
|
+
) }, "profile")
|
|
100
104
|
) : profileCard
|
|
101
105
|
]
|
|
102
106
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Avatar, Menu, List, Button, Link } from './chunk-
|
|
1
|
+
import { Avatar, Menu, List, Button, Link } from './chunk-3PO2SF7T.js';
|
|
2
2
|
import { cn } from './chunk-VU4CZ76T.js';
|
|
3
3
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|