highsoft-ui 1.0.141 → 1.0.143
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.md +75 -0
- package/dist/components/Sidebar/NavDisclosure.js +39 -0
- package/dist/components/Sidebar/NavGroup.js +74 -0
- package/dist/components/Sidebar/NavItem.js +28 -0
- package/dist/components/Sidebar/Sidebar.js +107 -0
- package/dist/components/Sidebar/SidebarLayout.js +95 -0
- package/dist/components/Sidebar/SidebarResizer.js +59 -0
- package/dist/components/Sidebar/context.js +18 -0
- package/dist/components/Sidebar/index.js +8 -0
- package/dist/highsoft-ui.css +1 -1
- package/dist/lib/components/Sidebar/NavDisclosure.d.ts +14 -0
- package/dist/lib/components/Sidebar/NavGroup.d.ts +25 -0
- package/dist/lib/components/Sidebar/NavItem.d.ts +15 -0
- package/dist/lib/components/Sidebar/Sidebar.d.ts +46 -0
- package/dist/lib/components/Sidebar/SidebarLayout.d.ts +41 -0
- package/dist/lib/components/Sidebar/SidebarResizer.d.ts +6 -0
- package/dist/lib/components/Sidebar/context.d.ts +29 -0
- package/dist/lib/components/Sidebar/index.d.ts +13 -0
- package/dist/lib/main.d.ts +2 -0
- package/dist/main.js +10 -2
- package/dist/styles.module-Bd4HbnpA.js +42 -0
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -208,9 +208,41 @@ The foundational layout component. Use it instead of raw `<div>` with inline sty
|
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
### InputSolo
|
|
211
|
+
Standalone, self-bordered text field with a floating label, help text, and error/success states.
|
|
211
212
|
```tsx
|
|
212
213
|
<InputSolo label="Email" placeholder="you@example.com" />
|
|
214
|
+
<InputSolo label="Search" size={300} iconLeft={<Icon name="search-md" />} />
|
|
215
|
+
<InputSolo label="API key" hasError helpText="That key isn't valid." />
|
|
213
216
|
```
|
|
217
|
+
- **`size`:** `100`, `200` (default), `300`
|
|
218
|
+
- **`variant`:** `"default"`, `"white"`
|
|
219
|
+
- **`iconLeft`:** icon rendered inside the field (not next to the label — that's `InputGrouped`'s `labelIcon`)
|
|
220
|
+
- **`hasError` / `success`:** state styling; pair with `helpText`
|
|
221
|
+
|
|
222
|
+
### SearchDropdown
|
|
223
|
+
Combobox / autocomplete: a search field (built on `InputSolo`) with a filtered, keyboard-navigable results popover and match highlighting.
|
|
224
|
+
```tsx
|
|
225
|
+
const items = [
|
|
226
|
+
{ id: 'chart.type', label: 'chart.type', kind: 'option' },
|
|
227
|
+
{ id: 'series.data', label: 'series.data', kind: 'option' },
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
<SearchDropdown
|
|
231
|
+
items={items}
|
|
232
|
+
placeholder="Search options…"
|
|
233
|
+
onSelect={(item) => router.push(`/api/${item.id}`)}
|
|
234
|
+
/>
|
|
235
|
+
|
|
236
|
+
// Server-side / async filtering — disable built-in filtering and feed results:
|
|
237
|
+
<SearchDropdown items={results} filter={false} onQueryChange={setQuery} mono />
|
|
238
|
+
```
|
|
239
|
+
- **`items`:** `SearchDropdownItem[]` — each `{ id, label, kind?, iconLeft?, disabled?, highlightFrom? }`
|
|
240
|
+
- **`onSelect(item)`:** called when a result is chosen; **`onQueryChange(query)`:** called as the user types
|
|
241
|
+
- **`filter`:** `true` (default, built-in substring match), `false` (you filter — pair with `onQueryChange`), or a custom `(item, query) => boolean`
|
|
242
|
+
- **`value` / `defaultValue`:** controlled / uncontrolled query
|
|
243
|
+
- **`size`:** `100` | `200` (default) | `300`; **`variant`:** `"default"` | `"white"` (forwarded to `InputSolo`)
|
|
244
|
+
- **`mono`:** monospace row labels (handy for code/API names); **`minChars`:** chars before the popover opens (default `1`)
|
|
245
|
+
- **`iconLeft`, `label`, `placeholder`, `emptyState`, `maxHeight`** also supported
|
|
214
246
|
|
|
215
247
|
### InputGrouped / SelectGrouped / FormGroup / FormRow
|
|
216
248
|
```tsx
|
|
@@ -284,6 +316,49 @@ const a = 2 // [!code ++]`} />
|
|
|
284
316
|
<Notification variant="danger" title="Error" message="Something went wrong" />
|
|
285
317
|
```
|
|
286
318
|
|
|
319
|
+
### Sidebar (SidebarLayout, Sidebar, NavItem, NavGroup, …)
|
|
320
|
+
A composable, resizable sidebar-navigation shell for docs/app layouts. The
|
|
321
|
+
`<SidebarLayout>` is a two-column grid that owns the resize width and the mobile
|
|
322
|
+
off-canvas drawer; compose the rest inside it.
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
import {
|
|
326
|
+
SidebarLayout, SidebarMain, Sidebar, SidebarHeader, SidebarBody,
|
|
327
|
+
SidebarSection, NavItem, NavGroup, NavDisclosure
|
|
328
|
+
} from 'highsoft-ui'
|
|
329
|
+
import { BarChart01 } from '@untitled-ui/icons-react'
|
|
330
|
+
|
|
331
|
+
<SidebarLayout storageKey="docs.sidebarWidth">
|
|
332
|
+
<Sidebar aria-label="Docs navigation">
|
|
333
|
+
<SidebarHeader>{/* logo, product switcher, search */}</SidebarHeader>
|
|
334
|
+
<SidebarBody>
|
|
335
|
+
<SidebarSection label="Getting started">
|
|
336
|
+
<NavItem href="/overview" active iconLeft={<BarChart01 />}>Overview</NavItem>
|
|
337
|
+
<NavItem href="/install">Installation</NavItem>
|
|
338
|
+
</SidebarSection>
|
|
339
|
+
<SidebarSection label="Components" collapsible>
|
|
340
|
+
<NavGroup label="Inputs" defaultOpen>
|
|
341
|
+
<NavItem href="/inputs/text">Text field</NavItem>
|
|
342
|
+
<NavItem href="/inputs/select">Select</NavItem>
|
|
343
|
+
</NavGroup>
|
|
344
|
+
<NavItem href="/button">Button</NavItem>
|
|
345
|
+
</SidebarSection>
|
|
346
|
+
</SidebarBody>
|
|
347
|
+
</Sidebar>
|
|
348
|
+
<SidebarMain>{children}</SidebarMain>
|
|
349
|
+
</SidebarLayout>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
- **`SidebarLayout`** — the grid shell. `defaultWidth`/`minWidth`/`maxWidth` (drag-to-resize), `storageKey` (persist width), `resizable` (default `true`), `fill` (default `true` — grows to fill a flex/grid parent), `mobileTriggerLabel` (default `"Menu"`). Owns the mobile drawer (sticky trigger, backdrop, Escape).
|
|
353
|
+
- **`SidebarMain`** — the fluid content column beside the sidebar.
|
|
354
|
+
- **`Sidebar`** — the `<aside>`; becomes the off-canvas drawer on mobile and auto-renders the resize handle + close button.
|
|
355
|
+
- **`SidebarHeader` / `SidebarBody`** — fixed top region / scrollable body.
|
|
356
|
+
- **`SidebarSection`** — labelled group. `collapsible` surfaces a "Minimize" control that collapses its open `NavGroup`s; `action` slots a custom control instead.
|
|
357
|
+
- **`NavItem`** — polymorphic nav link (`as`, default `<a>`); `active`, `icon`. Closes the mobile drawer on click. Open parents pin to the top while their list scrolls.
|
|
358
|
+
- **`NavGroup`** — expandable tree node (`defaultOpen`, controlled `open`/`onOpenChange`, `active` to tint the guide-line on the active path).
|
|
359
|
+
- **`NavDisclosure`** — collapses behind a tap-toggle on narrow screens, inert on desktop.
|
|
360
|
+
- The sidebar imposes **no background** of its own — set `--hs-sidebar-bg` (the mobile drawer keeps an opaque fallback). Colours use `--HS-*` tokens, so dark mode is automatic.
|
|
361
|
+
|
|
287
362
|
## Hooks
|
|
288
363
|
|
|
289
364
|
### useSuccessFlash
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../../clsx-BWCAbrjV.js";
|
|
3
|
+
import { t } from "../../styles.module-Bd4HbnpA.js";
|
|
4
|
+
import { useId as n, useState as r } from "react";
|
|
5
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
6
|
+
//#region lib/components/Sidebar/NavDisclosure.tsx
|
|
7
|
+
function o({ label: o, children: s, className: c }) {
|
|
8
|
+
let [l, u] = r(!1), d = n();
|
|
9
|
+
return /* @__PURE__ */ a("div", {
|
|
10
|
+
className: e(t.disclosure, c),
|
|
11
|
+
"data-open": l,
|
|
12
|
+
children: [/* @__PURE__ */ a("button", {
|
|
13
|
+
type: "button",
|
|
14
|
+
className: t.disclosureToggle,
|
|
15
|
+
"aria-expanded": l,
|
|
16
|
+
"aria-controls": d,
|
|
17
|
+
onClick: () => u((e) => !e),
|
|
18
|
+
children: [/* @__PURE__ */ i("svg", {
|
|
19
|
+
className: t.disclosureChevron,
|
|
20
|
+
width: "14",
|
|
21
|
+
height: "14",
|
|
22
|
+
viewBox: "0 0 24 24",
|
|
23
|
+
fill: "none",
|
|
24
|
+
stroke: "currentColor",
|
|
25
|
+
strokeWidth: "2.5",
|
|
26
|
+
strokeLinecap: "round",
|
|
27
|
+
strokeLinejoin: "round",
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
children: /* @__PURE__ */ i("path", { d: "m9 18 6-6-6-6" })
|
|
30
|
+
}), /* @__PURE__ */ i("span", { children: o })]
|
|
31
|
+
}), /* @__PURE__ */ i("div", {
|
|
32
|
+
id: d,
|
|
33
|
+
className: t.disclosureBody,
|
|
34
|
+
children: s
|
|
35
|
+
})]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { o as NavDisclosure };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../../clsx-BWCAbrjV.js";
|
|
3
|
+
import { useOptionalSidebarSection as t } from "./context.js";
|
|
4
|
+
import { t as n } from "../../styles.module-Bd4HbnpA.js";
|
|
5
|
+
import { createContext as r, useCallback as i, useContext as a, useEffect as o, useId as s, useRef as c, useState as l } from "react";
|
|
6
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
7
|
+
//#region lib/components/Sidebar/NavGroup.tsx
|
|
8
|
+
var f = r(0);
|
|
9
|
+
function p({ label: r, children: p, icon: m, defaultOpen: h = !1, open: g, onOpenChange: _, active: v, className: y }) {
|
|
10
|
+
let [b, x] = l(h), S = g !== void 0, C = S ? g : b, w = s(), T = s(), E = t(), D = a(f), O = i((e) => {
|
|
11
|
+
S || x(e), _?.(e);
|
|
12
|
+
}, [S, _]), k = i(() => O(!C), [C, O]);
|
|
13
|
+
o(() => (E?.reportOpen(T, C), () => E?.reportOpen(T, !1)), [
|
|
14
|
+
C,
|
|
15
|
+
T,
|
|
16
|
+
E
|
|
17
|
+
]);
|
|
18
|
+
let A = c(E?.collapseNonce ?? 0);
|
|
19
|
+
return o(() => {
|
|
20
|
+
let e = E?.collapseNonce ?? 0;
|
|
21
|
+
e !== A.current && (A.current = e, C && O(!1));
|
|
22
|
+
}, [
|
|
23
|
+
E?.collapseNonce,
|
|
24
|
+
C,
|
|
25
|
+
E,
|
|
26
|
+
O
|
|
27
|
+
]), /* @__PURE__ */ d("div", {
|
|
28
|
+
className: e(n.group, C && n.groupOpen, v && n.groupActive, y),
|
|
29
|
+
style: { "--hs-nav-depth": D },
|
|
30
|
+
children: [/* @__PURE__ */ d("button", {
|
|
31
|
+
type: "button",
|
|
32
|
+
className: n.groupToggle,
|
|
33
|
+
"aria-expanded": C,
|
|
34
|
+
"aria-controls": w,
|
|
35
|
+
onClick: k,
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ u("svg", {
|
|
38
|
+
className: n.groupChevron,
|
|
39
|
+
width: "14",
|
|
40
|
+
height: "14",
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
fill: "none",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
strokeWidth: "2.5",
|
|
45
|
+
strokeLinecap: "round",
|
|
46
|
+
strokeLinejoin: "round",
|
|
47
|
+
"aria-hidden": "true",
|
|
48
|
+
children: /* @__PURE__ */ u("path", { d: "m9 18 6-6-6-6" })
|
|
49
|
+
}),
|
|
50
|
+
m == null ? null : /* @__PURE__ */ u("span", {
|
|
51
|
+
className: n.itemIcon,
|
|
52
|
+
children: m
|
|
53
|
+
}),
|
|
54
|
+
/* @__PURE__ */ u("span", {
|
|
55
|
+
className: n.groupLabel,
|
|
56
|
+
children: r
|
|
57
|
+
})
|
|
58
|
+
]
|
|
59
|
+
}), /* @__PURE__ */ u("div", {
|
|
60
|
+
id: w,
|
|
61
|
+
className: n.groupChildren,
|
|
62
|
+
role: "group",
|
|
63
|
+
children: /* @__PURE__ */ u("div", {
|
|
64
|
+
className: n.groupChildrenInner,
|
|
65
|
+
children: /* @__PURE__ */ u(f.Provider, {
|
|
66
|
+
value: D + 1,
|
|
67
|
+
children: p
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
})]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { p as NavGroup };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../../clsx-BWCAbrjV.js";
|
|
3
|
+
import { useOptionalSidebarLayout as t } from "./context.js";
|
|
4
|
+
import { t as n } from "../../styles.module-Bd4HbnpA.js";
|
|
5
|
+
import { forwardRef as r } from "react";
|
|
6
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
7
|
+
//#region lib/components/Sidebar/NavItem.tsx
|
|
8
|
+
var o = r(function({ as: r, active: o, icon: s, children: c, className: l, onClick: u, ...d }, f) {
|
|
9
|
+
let p = r || "a", m = t();
|
|
10
|
+
return /* @__PURE__ */ a(p, {
|
|
11
|
+
ref: f,
|
|
12
|
+
className: e(n.item, o && n.itemActive, l),
|
|
13
|
+
"aria-current": o ? "page" : void 0,
|
|
14
|
+
onClick: (e) => {
|
|
15
|
+
u?.(e), m?.closeMobile();
|
|
16
|
+
},
|
|
17
|
+
...d,
|
|
18
|
+
children: [s == null ? null : /* @__PURE__ */ i("span", {
|
|
19
|
+
className: n.itemIcon,
|
|
20
|
+
children: s
|
|
21
|
+
}), /* @__PURE__ */ i("span", {
|
|
22
|
+
className: n.itemLabel,
|
|
23
|
+
children: c
|
|
24
|
+
})]
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//#endregion
|
|
28
|
+
export { o as NavItem };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../../clsx-BWCAbrjV.js";
|
|
3
|
+
import { t } from "../../Button-awCDIEXQ.js";
|
|
4
|
+
import { SidebarSectionContext as n, useSidebarLayout as r } from "./context.js";
|
|
5
|
+
import { t as i } from "../../styles.module-Bd4HbnpA.js";
|
|
6
|
+
import { SidebarResizer as a } from "./SidebarResizer.js";
|
|
7
|
+
import { useCallback as o, useEffect as s, useRef as c, useState as l } from "react";
|
|
8
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
9
|
+
//#region lib/components/Sidebar/Sidebar.tsx
|
|
10
|
+
function f({ children: t, "aria-label": n = "Sidebar navigation", closeLabel: o = "Close navigation", className: l }) {
|
|
11
|
+
let { resizable: f, mobileOpen: p, closeMobile: m } = r(), h = c(null);
|
|
12
|
+
return s(() => {
|
|
13
|
+
p && h.current?.focus();
|
|
14
|
+
}, [p]), /* @__PURE__ */ d("aside", {
|
|
15
|
+
id: "hs-sidebar-drawer",
|
|
16
|
+
className: e(i.sidebar, p && i.sidebarOpen, l),
|
|
17
|
+
"aria-label": n,
|
|
18
|
+
children: [
|
|
19
|
+
/* @__PURE__ */ u("button", {
|
|
20
|
+
ref: h,
|
|
21
|
+
type: "button",
|
|
22
|
+
className: i.close,
|
|
23
|
+
"aria-label": o,
|
|
24
|
+
onClick: m,
|
|
25
|
+
children: /* @__PURE__ */ u(_, {})
|
|
26
|
+
}),
|
|
27
|
+
t,
|
|
28
|
+
f ? /* @__PURE__ */ u(a, {}) : null
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function p({ children: t, className: n }) {
|
|
33
|
+
return /* @__PURE__ */ u("div", {
|
|
34
|
+
className: e(i.header, n),
|
|
35
|
+
children: t
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function m({ children: t, className: n }) {
|
|
39
|
+
return /* @__PURE__ */ u("div", {
|
|
40
|
+
className: e(i.body, n),
|
|
41
|
+
children: t
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function h({ children: r, label: a, collapsible: s = !1, minimizeLabel: f = "Minimize", action: p, className: m }) {
|
|
45
|
+
let [h, _] = l(0), v = c(/* @__PURE__ */ new Set()), [y, b] = l(0), x = o((e, t) => {
|
|
46
|
+
let n = v.current;
|
|
47
|
+
t ? n.add(e) : n.delete(e), b(n.size);
|
|
48
|
+
}, []), S = s && p == null && y > 0, C = a != null || p != null || S;
|
|
49
|
+
return /* @__PURE__ */ u(n.Provider, {
|
|
50
|
+
value: {
|
|
51
|
+
collapseNonce: h,
|
|
52
|
+
reportOpen: x
|
|
53
|
+
},
|
|
54
|
+
children: /* @__PURE__ */ d("section", {
|
|
55
|
+
className: e(i.section, C && i.hasStickyHead, m),
|
|
56
|
+
children: [C ? /* @__PURE__ */ d("div", {
|
|
57
|
+
className: i.sectionHead,
|
|
58
|
+
children: [a == null ? null : /* @__PURE__ */ u("h3", {
|
|
59
|
+
className: i.sectionLabel,
|
|
60
|
+
children: a
|
|
61
|
+
}), p ?? (S ? /* @__PURE__ */ u(t, {
|
|
62
|
+
variant: "plain",
|
|
63
|
+
size: 100,
|
|
64
|
+
className: i.minimizeBtn,
|
|
65
|
+
iconLeft: /* @__PURE__ */ u(g, {}),
|
|
66
|
+
onClick: () => _((e) => e + 1),
|
|
67
|
+
children: f
|
|
68
|
+
}) : null)]
|
|
69
|
+
}) : null, r]
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function g() {
|
|
74
|
+
return /* @__PURE__ */ d("svg", {
|
|
75
|
+
width: "14",
|
|
76
|
+
height: "14",
|
|
77
|
+
viewBox: "0 0 16 16",
|
|
78
|
+
fill: "none",
|
|
79
|
+
stroke: "currentColor",
|
|
80
|
+
strokeWidth: "1.25",
|
|
81
|
+
strokeLinecap: "round",
|
|
82
|
+
strokeLinejoin: "round",
|
|
83
|
+
"aria-hidden": "true",
|
|
84
|
+
children: [/* @__PURE__ */ u("rect", {
|
|
85
|
+
x: "2.5",
|
|
86
|
+
y: "2.5",
|
|
87
|
+
width: "11",
|
|
88
|
+
height: "11",
|
|
89
|
+
rx: "2"
|
|
90
|
+
}), /* @__PURE__ */ u("path", { d: "M5.5 8h5" })]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function _() {
|
|
94
|
+
return /* @__PURE__ */ u("svg", {
|
|
95
|
+
width: "18",
|
|
96
|
+
height: "18",
|
|
97
|
+
viewBox: "0 0 24 24",
|
|
98
|
+
fill: "none",
|
|
99
|
+
stroke: "currentColor",
|
|
100
|
+
strokeWidth: "2",
|
|
101
|
+
strokeLinecap: "round",
|
|
102
|
+
"aria-hidden": "true",
|
|
103
|
+
children: /* @__PURE__ */ u("path", { d: "M18 6 6 18M6 6l12 12" })
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
export { f as Sidebar, m as SidebarBody, p as SidebarHeader, h as SidebarSection };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../../clsx-BWCAbrjV.js";
|
|
3
|
+
import { SidebarLayoutContext as t } from "./context.js";
|
|
4
|
+
import { t as n } from "../../styles.module-Bd4HbnpA.js";
|
|
5
|
+
import { useCallback as r, useEffect as i, useRef as a, useState as o } from "react";
|
|
6
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
7
|
+
//#region lib/components/Sidebar/SidebarLayout.tsx
|
|
8
|
+
function l({ children: l, defaultWidth: u = 320, minWidth: f = 230, maxWidth: p = 460, resizable: m = !0, storageKey: h, mobileTriggerLabel: g = "Menu", fill: _ = !0, className: v, style: y }) {
|
|
9
|
+
let [b, x] = o(u), [S, C] = o(!1), w = a(null), T = r((e) => {
|
|
10
|
+
let t = Math.min(Math.max(Math.round(e), f), p);
|
|
11
|
+
if (x(t), h) try {
|
|
12
|
+
localStorage.setItem(h, String(t));
|
|
13
|
+
} catch {}
|
|
14
|
+
}, [
|
|
15
|
+
f,
|
|
16
|
+
p,
|
|
17
|
+
h
|
|
18
|
+
]);
|
|
19
|
+
i(() => {
|
|
20
|
+
if (h) try {
|
|
21
|
+
let e = localStorage.getItem(h);
|
|
22
|
+
e && T(Number(e) || u);
|
|
23
|
+
} catch {}
|
|
24
|
+
}, []);
|
|
25
|
+
let E = r(() => {
|
|
26
|
+
C(!1), w.current?.focus();
|
|
27
|
+
}, []), D = r(() => C(!0), []);
|
|
28
|
+
return i(() => {
|
|
29
|
+
if (!S) return;
|
|
30
|
+
let e = (e) => {
|
|
31
|
+
e.key === "Escape" && E();
|
|
32
|
+
};
|
|
33
|
+
return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
|
|
34
|
+
}, [S, E]), /* @__PURE__ */ s(t.Provider, {
|
|
35
|
+
value: {
|
|
36
|
+
resizable: m,
|
|
37
|
+
width: b,
|
|
38
|
+
setWidth: T,
|
|
39
|
+
minWidth: f,
|
|
40
|
+
maxWidth: p,
|
|
41
|
+
mobileOpen: S,
|
|
42
|
+
openMobile: D,
|
|
43
|
+
closeMobile: E
|
|
44
|
+
},
|
|
45
|
+
children: /* @__PURE__ */ c("div", {
|
|
46
|
+
className: e(n.layout, _ && n.fill, v),
|
|
47
|
+
style: {
|
|
48
|
+
"--hs-sidebar-w": `${b}px`,
|
|
49
|
+
...y
|
|
50
|
+
},
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ s("div", {
|
|
53
|
+
className: n.mobileBar,
|
|
54
|
+
children: /* @__PURE__ */ c("button", {
|
|
55
|
+
ref: w,
|
|
56
|
+
type: "button",
|
|
57
|
+
className: n.trigger,
|
|
58
|
+
"aria-expanded": S,
|
|
59
|
+
"aria-controls": "hs-sidebar-drawer",
|
|
60
|
+
onClick: D,
|
|
61
|
+
children: [/* @__PURE__ */ s(d, {}), g]
|
|
62
|
+
})
|
|
63
|
+
}),
|
|
64
|
+
l,
|
|
65
|
+
/* @__PURE__ */ s("div", {
|
|
66
|
+
className: e(n.backdrop, S && n.backdropOpen),
|
|
67
|
+
onClick: E,
|
|
68
|
+
"aria-hidden": "true"
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function u({ children: t, className: r, ...i }) {
|
|
75
|
+
return /* @__PURE__ */ s("main", {
|
|
76
|
+
className: e(n.main, r),
|
|
77
|
+
...i,
|
|
78
|
+
children: t
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function d() {
|
|
82
|
+
return /* @__PURE__ */ s("svg", {
|
|
83
|
+
width: "18",
|
|
84
|
+
height: "18",
|
|
85
|
+
viewBox: "0 0 24 24",
|
|
86
|
+
fill: "none",
|
|
87
|
+
stroke: "currentColor",
|
|
88
|
+
strokeWidth: "2",
|
|
89
|
+
strokeLinecap: "round",
|
|
90
|
+
"aria-hidden": "true",
|
|
91
|
+
children: /* @__PURE__ */ s("path", { d: "M3 6h18M3 12h18M3 18h18" })
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { l as SidebarLayout, u as SidebarMain };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useSidebarLayout as e } from "./context.js";
|
|
3
|
+
import { t } from "../../styles.module-Bd4HbnpA.js";
|
|
4
|
+
import { useCallback as n, useEffect as r, useRef as i, useState as a } from "react";
|
|
5
|
+
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
6
|
+
//#region lib/components/Sidebar/SidebarResizer.tsx
|
|
7
|
+
function l() {
|
|
8
|
+
let { width: l, setWidth: u, minWidth: d, maxWidth: f } = e(), p = i(null), m = i(!1), [h, g] = a(!1), [_, v] = a(!1);
|
|
9
|
+
r(() => {
|
|
10
|
+
function e(e) {
|
|
11
|
+
if (!m.current || !p.current) return;
|
|
12
|
+
let t = p.current.parentElement;
|
|
13
|
+
if (!t) return;
|
|
14
|
+
let n = p.current.offsetWidth / 2;
|
|
15
|
+
u(e.clientX - t.getBoundingClientRect().left + n);
|
|
16
|
+
}
|
|
17
|
+
function t() {
|
|
18
|
+
m.current = !1, g(!1), document.body.style.userSelect = "";
|
|
19
|
+
}
|
|
20
|
+
return window.addEventListener("mousemove", e), window.addEventListener("mouseup", t), () => {
|
|
21
|
+
window.removeEventListener("mousemove", e), window.removeEventListener("mouseup", t);
|
|
22
|
+
};
|
|
23
|
+
}, [u]);
|
|
24
|
+
let y = n(() => {
|
|
25
|
+
m.current = !0, g(!0), document.body.style.userSelect = "none";
|
|
26
|
+
}, []), b = _ || h;
|
|
27
|
+
return /* @__PURE__ */ c(o, { children: [
|
|
28
|
+
/* @__PURE__ */ s("div", {
|
|
29
|
+
className: t.hatchClip,
|
|
30
|
+
"aria-hidden": "true",
|
|
31
|
+
children: /* @__PURE__ */ s("div", { className: `${t.hatchInner}${b ? ` ${t.hatchHi}` : ""}${h ? ` ${t.hatchDrag}` : ""}` })
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ s("div", {
|
|
34
|
+
ref: p,
|
|
35
|
+
className: t.handle,
|
|
36
|
+
onMouseDown: y,
|
|
37
|
+
onPointerEnter: () => v(!0),
|
|
38
|
+
onPointerLeave: () => v(!1),
|
|
39
|
+
onFocus: () => v(!0),
|
|
40
|
+
onBlur: () => v(!1),
|
|
41
|
+
onKeyDown: (e) => {
|
|
42
|
+
(e.key === "ArrowLeft" || e.key === "ArrowRight") && (e.preventDefault(), u(l + (e.key === "ArrowLeft" ? -16 : 16)));
|
|
43
|
+
},
|
|
44
|
+
tabIndex: 0,
|
|
45
|
+
role: "separator",
|
|
46
|
+
"aria-orientation": "vertical",
|
|
47
|
+
"aria-label": "Resize sidebar",
|
|
48
|
+
"aria-valuenow": l,
|
|
49
|
+
"aria-valuemin": d,
|
|
50
|
+
"aria-valuemax": f
|
|
51
|
+
}),
|
|
52
|
+
h ? /* @__PURE__ */ s("div", {
|
|
53
|
+
className: t.overlay,
|
|
54
|
+
"aria-hidden": "true"
|
|
55
|
+
}) : null
|
|
56
|
+
] });
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { l as SidebarResizer };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext as e, useContext as t } from "react";
|
|
3
|
+
//#region lib/components/Sidebar/context.ts
|
|
4
|
+
var n = e(null);
|
|
5
|
+
function r() {
|
|
6
|
+
let e = t(n);
|
|
7
|
+
if (!e) throw Error("Sidebar components must be rendered within <SidebarLayout>");
|
|
8
|
+
return e;
|
|
9
|
+
}
|
|
10
|
+
function i() {
|
|
11
|
+
return t(n);
|
|
12
|
+
}
|
|
13
|
+
var a = e(null);
|
|
14
|
+
function o() {
|
|
15
|
+
return t(a);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { n as SidebarLayoutContext, a as SidebarSectionContext, i as useOptionalSidebarLayout, o as useOptionalSidebarSection, r as useSidebarLayout };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useOptionalSidebarLayout as e, useSidebarLayout as t } from "./context.js";
|
|
2
|
+
import { SidebarLayout as n, SidebarMain as r } from "./SidebarLayout.js";
|
|
3
|
+
import { SidebarResizer as i } from "./SidebarResizer.js";
|
|
4
|
+
import { Sidebar as a, SidebarBody as o, SidebarHeader as s, SidebarSection as c } from "./Sidebar.js";
|
|
5
|
+
import { NavItem as l } from "./NavItem.js";
|
|
6
|
+
import { NavGroup as u } from "./NavGroup.js";
|
|
7
|
+
import { NavDisclosure as d } from "./NavDisclosure.js";
|
|
8
|
+
export { d as NavDisclosure, u as NavGroup, l as NavItem, a as Sidebar, o as SidebarBody, s as SidebarHeader, n as SidebarLayout, r as SidebarMain, i as SidebarResizer, c as SidebarSection, e as useOptionalSidebarLayout, t as useSidebarLayout };
|