@marktiderman/genesis-ui 2.15.0 → 2.17.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/SKILL.md +2 -1
- package/dist/{AppShell-HCXpi6nv.d.ts → AppShell-DDyVqNmJ.d.ts} +12 -2
- package/dist/{chunk-46TZGMFW.js → chunk-24NUW3QN.js} +22 -22
- package/dist/chunk-24NUW3QN.js.map +1 -0
- package/dist/{chunk-DTQHAZWN.js → chunk-3FKF2SN4.js} +19 -5
- package/dist/chunk-3FKF2SN4.js.map +1 -0
- package/dist/{chunk-25XEXYGC.js → chunk-OT6KKSD2.js} +20 -20
- package/dist/chunk-OT6KKSD2.js.map +1 -0
- package/dist/{chunk-STZVZUYO.js → chunk-TQ7OJDSU.js} +8 -6
- package/dist/chunk-TQ7OJDSU.js.map +1 -0
- package/dist/chunk-YCQAYWMX.js +192 -0
- package/dist/chunk-YCQAYWMX.js.map +1 -0
- package/dist/components/data/index.d.ts +6 -6
- package/dist/components/data/index.js +170 -123
- package/dist/components/data/index.js.map +1 -1
- package/dist/components/layout/detail-page.d.ts +1 -1
- package/dist/components/layout/index.d.ts +27 -11
- package/dist/components/layout/index.js +73 -23
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/settings-page.d.ts +1 -1
- package/dist/components/patterns/index.js +3 -2
- package/dist/components/patterns/sortable-list.js +2 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/use-resource-page.d.ts +1 -1
- package/dist/index.d.ts +176 -2
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/{split-Dk9f4Mi0.d.ts → split-D-uYckQ_.d.ts} +1 -1
- package/dist/{use-resource-page-DaJzuq3M.d.ts → use-resource-page-BA1P7xea.d.ts} +1 -1
- package/dist/{use-resource-table-easmRDQI.d.ts → use-resource-table-WDqz7oQ-.d.ts} +17 -3
- package/package.json +2 -2
- package/dist/chunk-25XEXYGC.js.map +0 -1
- package/dist/chunk-46TZGMFW.js.map +0 -1
- package/dist/chunk-DTQHAZWN.js.map +0 -1
- package/dist/chunk-STZVZUYO.js.map +0 -1
package/SKILL.md
CHANGED
|
@@ -386,7 +386,8 @@ most specific sibling wins) and an optional `badge` (a count or short status, sh
|
|
|
386
386
|
it over.
|
|
387
387
|
For live data (badge counts) the page calls `useAppShellSubNav(items, { mode? })`, which
|
|
388
388
|
replaces the node's items while it is mounted, and puts a host chip at the end of the tab row with
|
|
389
|
-
`<AppShellSubNavEnd>…</AppShellSubNavEnd
|
|
389
|
+
`<AppShellSubNavEnd>…</AppShellSubNavEnd>` (on phones, where the bottom bar replaces the row,
|
|
390
|
+
the chip moves to a compact strip under the page header, so it stays reachable). The page's resource header (breadcrumb, title,
|
|
390
391
|
status, actions) goes in `<AppShellPageHeader>…</AppShellPageHeader>`, which the shell renders
|
|
391
392
|
above the tab row (on phones too; at the top of the content when there is no row). Both are
|
|
392
393
|
portals; when a layout and its page both mount one, the page's (innermost) renders, and the same
|
|
@@ -31,6 +31,14 @@ type SubNavMode = "section" | "tabs" | "sidebar" | "off";
|
|
|
31
31
|
interface SubNavItem extends Omit<NavItem, "icon" | "children"> {
|
|
32
32
|
icon?: LucideIcon;
|
|
33
33
|
children?: SubNavItem[];
|
|
34
|
+
/**
|
|
35
|
+
* Leave this item out of the phone bar (it stays in the tab row, the
|
|
36
|
+
* sidebar and the rail). The phone bar fits back plus about four items:
|
|
37
|
+
* fold a builder panel into its parent tab on phones instead of
|
|
38
|
+
* overflowing. If its route sits under another item's (without `end`),
|
|
39
|
+
* that item shows as current while it is open.
|
|
40
|
+
*/
|
|
41
|
+
hideOnPhone?: boolean;
|
|
34
42
|
}
|
|
35
43
|
/**
|
|
36
44
|
* Props for {@link SubNavTabs}.
|
|
@@ -93,8 +101,10 @@ declare function useAppShellSubNav(items: SubNavItem[] | null | undefined, optio
|
|
|
93
101
|
/**
|
|
94
102
|
* Render `children` in the right-hand slot of the shell's sub-navigation
|
|
95
103
|
* tab row, e.g. a "Ready to publish" status chip. Rendered through a
|
|
96
|
-
* portal, so it keeps the page's context and state.
|
|
97
|
-
*
|
|
104
|
+
* portal, so it keeps the page's context and state. On phones, where the
|
|
105
|
+
* bottom bar replaces the tab row, it renders in a compact strip under the
|
|
106
|
+
* page header instead, so the chip stays reachable. Renders nothing when
|
|
107
|
+
* the shell has no tab row (other modes, a page without children). When
|
|
98
108
|
* several are mounted (a layout's and a page's), the innermost renders.
|
|
99
109
|
*
|
|
100
110
|
* @stability Beta
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from './chunk-FK42ZGGV.js';
|
|
2
2
|
import { Popover, PopoverTrigger, PopoverContent } from './chunk-22XB3Q6H.js';
|
|
3
3
|
import { Button } from './chunk-NWSCYLPT.js';
|
|
4
|
+
import { useUiMessages, fillMessage } from './chunk-YCQAYWMX.js';
|
|
4
5
|
import { LayoutGrid, Table2, List, Settings2 } from 'lucide-react';
|
|
5
6
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
7
|
import { useId } from 'react';
|
|
7
8
|
|
|
8
9
|
function ViewToggle({ viewMode, onViewModeChange }) {
|
|
10
|
+
const m = useUiMessages();
|
|
9
11
|
return /* @__PURE__ */ jsxs(
|
|
10
12
|
"div",
|
|
11
13
|
{
|
|
12
14
|
className: "flex items-center border rounded-lg overflow-hidden",
|
|
13
15
|
role: "group",
|
|
14
|
-
"aria-label":
|
|
16
|
+
"aria-label": m.view.mode,
|
|
15
17
|
children: [
|
|
16
18
|
/* @__PURE__ */ jsx(
|
|
17
19
|
Button,
|
|
@@ -20,8 +22,8 @@ function ViewToggle({ viewMode, onViewModeChange }) {
|
|
|
20
22
|
size: "icon",
|
|
21
23
|
className: "h-8 w-8 rounded-none",
|
|
22
24
|
onClick: () => onViewModeChange("grid"),
|
|
23
|
-
title:
|
|
24
|
-
"aria-label":
|
|
25
|
+
title: m.view.grid,
|
|
26
|
+
"aria-label": m.view.grid,
|
|
25
27
|
"aria-pressed": viewMode === "grid",
|
|
26
28
|
testID: "view-toggle-grid",
|
|
27
29
|
children: /* @__PURE__ */ jsx(LayoutGrid, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
@@ -34,8 +36,8 @@ function ViewToggle({ viewMode, onViewModeChange }) {
|
|
|
34
36
|
size: "icon",
|
|
35
37
|
className: "h-8 w-8 rounded-none",
|
|
36
38
|
onClick: () => onViewModeChange("table"),
|
|
37
|
-
title:
|
|
38
|
-
"aria-label":
|
|
39
|
+
title: m.view.table,
|
|
40
|
+
"aria-label": m.view.table,
|
|
39
41
|
"aria-pressed": viewMode === "table",
|
|
40
42
|
testID: "view-toggle-table",
|
|
41
43
|
children: /* @__PURE__ */ jsx(Table2, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
@@ -48,8 +50,8 @@ function ViewToggle({ viewMode, onViewModeChange }) {
|
|
|
48
50
|
size: "icon",
|
|
49
51
|
className: "h-8 w-8 rounded-none",
|
|
50
52
|
onClick: () => onViewModeChange("list"),
|
|
51
|
-
title:
|
|
52
|
-
"aria-label":
|
|
53
|
+
title: m.view.list,
|
|
54
|
+
"aria-label": m.view.list,
|
|
53
55
|
"aria-pressed": viewMode === "list",
|
|
54
56
|
testID: "view-toggle-list",
|
|
55
57
|
children: /* @__PURE__ */ jsx(List, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
@@ -61,9 +63,9 @@ function ViewToggle({ viewMode, onViewModeChange }) {
|
|
|
61
63
|
}
|
|
62
64
|
var PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
|
|
63
65
|
var DENSITY_OPTIONS = [
|
|
64
|
-
{ value: "compact", label: "
|
|
65
|
-
{ value: "comfortable", label: "
|
|
66
|
-
{ value: "spacious", label: "
|
|
66
|
+
{ value: "compact", label: "compact" },
|
|
67
|
+
{ value: "comfortable", label: "comfortable" },
|
|
68
|
+
{ value: "spacious", label: "spacious" }
|
|
67
69
|
];
|
|
68
70
|
function ViewSettings({
|
|
69
71
|
pageSize,
|
|
@@ -71,6 +73,7 @@ function ViewSettings({
|
|
|
71
73
|
density,
|
|
72
74
|
onDensityChange
|
|
73
75
|
}) {
|
|
76
|
+
const m = useUiMessages();
|
|
74
77
|
const baseId = useId();
|
|
75
78
|
const pageSizeLabelId = `${baseId}-page-size`;
|
|
76
79
|
const densityLabelId = `${baseId}-density`;
|
|
@@ -81,21 +84,21 @@ function ViewSettings({
|
|
|
81
84
|
variant: "ghost",
|
|
82
85
|
size: "icon",
|
|
83
86
|
className: "h-8 w-8",
|
|
84
|
-
title:
|
|
85
|
-
"aria-label":
|
|
87
|
+
title: m.view.settings,
|
|
88
|
+
"aria-label": m.view.settings,
|
|
86
89
|
testID: "view-settings-trigger",
|
|
87
90
|
children: /* @__PURE__ */ jsx(Settings2, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
88
91
|
}
|
|
89
92
|
) }),
|
|
90
93
|
/* @__PURE__ */ jsxs(PopoverContent, { align: "end", className: "w-56 space-y-4", children: [
|
|
91
|
-
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold", children:
|
|
94
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold", children: m.view.settingsTitle }),
|
|
92
95
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
93
96
|
/* @__PURE__ */ jsx(
|
|
94
97
|
"span",
|
|
95
98
|
{
|
|
96
99
|
id: pageSizeLabelId,
|
|
97
100
|
className: "block text-xs text-muted-foreground",
|
|
98
|
-
children:
|
|
101
|
+
children: m.view.pageSize
|
|
99
102
|
}
|
|
100
103
|
),
|
|
101
104
|
/* @__PURE__ */ jsxs(
|
|
@@ -113,10 +116,7 @@ function ViewSettings({
|
|
|
113
116
|
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
114
117
|
}
|
|
115
118
|
),
|
|
116
|
-
/* @__PURE__ */ jsx(SelectContent, { className: "bg-popover z-50", children: PAGE_SIZE_OPTIONS.map((n) => /* @__PURE__ */
|
|
117
|
-
n,
|
|
118
|
-
" items"
|
|
119
|
-
] }, n)) })
|
|
119
|
+
/* @__PURE__ */ jsx(SelectContent, { className: "bg-popover z-50", children: PAGE_SIZE_OPTIONS.map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), children: fillMessage(m.view.pageSizeOption, { n }) }, n)) })
|
|
120
120
|
]
|
|
121
121
|
}
|
|
122
122
|
)
|
|
@@ -127,7 +127,7 @@ function ViewSettings({
|
|
|
127
127
|
{
|
|
128
128
|
id: densityLabelId,
|
|
129
129
|
className: "block text-xs text-muted-foreground",
|
|
130
|
-
children:
|
|
130
|
+
children: m.view.density
|
|
131
131
|
}
|
|
132
132
|
),
|
|
133
133
|
/* @__PURE__ */ jsxs(
|
|
@@ -145,7 +145,7 @@ function ViewSettings({
|
|
|
145
145
|
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
146
146
|
}
|
|
147
147
|
),
|
|
148
|
-
/* @__PURE__ */ jsx(SelectContent, { className: "bg-popover z-50", children: DENSITY_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
|
|
148
|
+
/* @__PURE__ */ jsx(SelectContent, { className: "bg-popover z-50", children: DENSITY_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: m.view[opt.label] }, opt.value)) })
|
|
149
149
|
]
|
|
150
150
|
}
|
|
151
151
|
)
|
|
@@ -155,5 +155,5 @@ function ViewSettings({
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
export { ViewSettings, ViewToggle };
|
|
158
|
-
//# sourceMappingURL=chunk-
|
|
159
|
-
//# sourceMappingURL=chunk-
|
|
158
|
+
//# sourceMappingURL=chunk-24NUW3QN.js.map
|
|
159
|
+
//# sourceMappingURL=chunk-24NUW3QN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/patterns/view-toggle.tsx","../src/components/patterns/view-settings.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"chunk-24NUW3QN.js","sourcesContent":["import { Button } from \"../ui/button\";\nimport { LayoutGrid, Table2, List } from \"lucide-react\";\nimport { useUiMessages } from \"../../messages\";\n\nexport type ViewMode = \"grid\" | \"table\" | \"list\";\n\ninterface ViewToggleProps {\n viewMode: ViewMode;\n onViewModeChange: (mode: ViewMode) => void;\n}\n\nexport function ViewToggle({ viewMode, onViewModeChange }: ViewToggleProps) {\n const m = useUiMessages();\n // Each button is icon-only, so `aria-label` supplies the accessible name\n // (`title` alone is not a reliable one) and `aria-pressed` reports which of\n // the three is current — the `default`/`ghost` variant swap conveys that to\n // sighted users only.\n return (\n <div\n className=\"flex items-center border rounded-lg overflow-hidden\"\n role=\"group\"\n aria-label={m.view.mode}\n >\n <Button\n variant={viewMode === \"grid\" ? \"default\" : \"ghost\"}\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n onClick={() => onViewModeChange(\"grid\")}\n title={m.view.grid}\n aria-label={m.view.grid}\n aria-pressed={viewMode === \"grid\"}\n testID=\"view-toggle-grid\"\n >\n <LayoutGrid className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n <Button\n variant={viewMode === \"table\" ? \"default\" : \"ghost\"}\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n onClick={() => onViewModeChange(\"table\")}\n title={m.view.table}\n aria-label={m.view.table}\n aria-pressed={viewMode === \"table\"}\n testID=\"view-toggle-table\"\n >\n <Table2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n <Button\n variant={viewMode === \"list\" ? \"default\" : \"ghost\"}\n size=\"icon\"\n className=\"h-8 w-8 rounded-none\"\n onClick={() => onViewModeChange(\"list\")}\n title={m.view.list}\n aria-label={m.view.list}\n aria-pressed={viewMode === \"list\"}\n testID=\"view-toggle-list\"\n >\n <List className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n );\n}\n","import { useId } from \"react\";\nimport { Settings2 } from \"lucide-react\";\nimport { fillMessage, useUiMessages } from \"../../messages\";\nimport { Button } from \"../ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../ui/select\";\nimport type { Density } from \"../../hooks/use-view-settings\";\n\ninterface ViewSettingsProps {\n pageSize: number;\n onPageSizeChange: (size: number) => void;\n density: Density;\n onDensityChange: (density: Density) => void;\n}\n\nconst PAGE_SIZE_OPTIONS = [10, 25, 50, 100];\nconst DENSITY_OPTIONS: { value: Density; label: \"compact\" | \"comfortable\" | \"spacious\" }[] = [\n { value: \"compact\", label: \"compact\" },\n { value: \"comfortable\", label: \"comfortable\" },\n { value: \"spacious\", label: \"spacious\" },\n];\n\nexport function ViewSettings({\n pageSize,\n onPageSizeChange,\n density,\n onDensityChange,\n}: ViewSettingsProps) {\n const m = useUiMessages();\n // Radix renders each `SelectTrigger` as a <button>, and a <label> cannot be\n // associated with a button via `htmlFor`. `aria-labelledby` pointing at the\n // visible label is the association that actually reaches assistive tech.\n // `useId` keeps the ids unique when more than one ViewSettings is mounted.\n const baseId = useId();\n const pageSizeLabelId = `${baseId}-page-size`;\n const densityLabelId = `${baseId}-density`;\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8\"\n title={m.view.settings}\n // Icon-only trigger: `title` is not a dependable accessible name.\n aria-label={m.view.settings}\n testID=\"view-settings-trigger\"\n >\n <Settings2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-56 space-y-4\">\n <h4 className=\"text-sm font-semibold\">{m.view.settingsTitle}</h4>\n\n <div className=\"space-y-2\">\n <span\n id={pageSizeLabelId}\n className=\"block text-xs text-muted-foreground\"\n >\n {m.view.pageSize}\n </span>\n <Select\n value={String(pageSize)}\n onValueChange={(v) => onPageSizeChange(Number(v))}\n >\n <SelectTrigger\n className=\"h-8 text-xs\"\n aria-labelledby={pageSizeLabelId}\n data-testid=\"view-settings-page-size\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent className=\"bg-popover z-50\">\n {PAGE_SIZE_OPTIONS.map((n) => (\n <SelectItem key={n} value={String(n)}>\n {fillMessage(m.view.pageSizeOption, { n })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <span\n id={densityLabelId}\n className=\"block text-xs text-muted-foreground\"\n >\n {m.view.density}\n </span>\n <Select\n value={density}\n onValueChange={(v) => onDensityChange(v as Density)}\n >\n <SelectTrigger\n className=\"h-8 text-xs\"\n aria-labelledby={densityLabelId}\n data-testid=\"view-settings-density\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent className=\"bg-popover z-50\">\n {DENSITY_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {m.view[opt.label]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { ViewToggle, ViewSettings } from './chunk-
|
|
2
|
+
import { ViewToggle, ViewSettings } from './chunk-24NUW3QN.js';
|
|
3
3
|
import { Collapsible, CollapsibleContent } from './chunk-B2GIBUQD.js';
|
|
4
4
|
import { Badge } from './chunk-NPNADZHM.js';
|
|
5
5
|
import { Tooltip } from './chunk-G5YKBPBF.js';
|
|
@@ -10,6 +10,7 @@ import { Switch } from './chunk-27ELYTGE.js';
|
|
|
10
10
|
import { Label } from './chunk-F47U5KNW.js';
|
|
11
11
|
import { cn } from './chunk-NZ5WBA4R.js';
|
|
12
12
|
import { isPathActive, resolveNavigation, DefaultLink } from './chunk-J45FHL7D.js';
|
|
13
|
+
import { useIsMobile } from './chunk-VFO3I7PV.js';
|
|
13
14
|
import { createContext, useId, useState, useEffect, useMemo, useCallback, useContext, useRef, useLayoutEffect, useSyncExternalStore } from 'react';
|
|
14
15
|
import { ListFilter, MoreHorizontal, SlidersHorizontal, Menu, ArrowLeft, X, Sun, Moon, PanelLeft, PanelLeftClose, ChevronRight, ChevronDown } from 'lucide-react';
|
|
15
16
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -1416,7 +1417,7 @@ function AppShell({
|
|
|
1416
1417
|
const subActive = contextualNavItems.some((i) => itemIsActive(i, activePath, isActive));
|
|
1417
1418
|
const subNavOn = subNavMode === "tabs" || subNavMode === "sidebar";
|
|
1418
1419
|
const leaves = (items) => items.filter((i) => !i.children || i.children.length === 0);
|
|
1419
|
-
const contextualLeaves = subNavMode === "off" ? [] : leaves(contextualNavItems);
|
|
1420
|
+
const contextualLeaves = subNavMode === "off" ? [] : leaves(contextualNavItems).filter((i) => !i.hideOnPhone);
|
|
1420
1421
|
const subBottom = subNavOn && contextualLeaves.length > 0;
|
|
1421
1422
|
const legacyBottom = !subNavOn && !mobileNavItems && contextualLeaves.length > 0;
|
|
1422
1423
|
const backTarget = subBottom ? parentNavigation ?? derived?.backItem ?? (() => {
|
|
@@ -1454,6 +1455,8 @@ function AppShell({
|
|
|
1454
1455
|
const showUser = hasUser && resolved.showUserSlot !== false;
|
|
1455
1456
|
const showMobileBottom = bottomItems.length > 0 && resolved.showMobileBottomNav !== false;
|
|
1456
1457
|
const showTabs = subNavMode === "tabs" && contextualNavItems.length > 0;
|
|
1458
|
+
const isPhone = useIsMobile();
|
|
1459
|
+
const endOnPhone = showTabs && showMobileBottom && isPhone && subNavChannel.hasEnd;
|
|
1457
1460
|
const optionsControl = resolved.configurable && toggles.length > 0 ? /* @__PURE__ */ jsxs(Popover, { children: [
|
|
1458
1461
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
1459
1462
|
Button,
|
|
@@ -1758,6 +1761,17 @@ function AppShell({
|
|
|
1758
1761
|
"data-testid": "app-shell-page-header"
|
|
1759
1762
|
}
|
|
1760
1763
|
) : null,
|
|
1764
|
+
endOnPhone ? /* @__PURE__ */ jsx(
|
|
1765
|
+
"div",
|
|
1766
|
+
{
|
|
1767
|
+
ref: subNavChannel.setEndSlot,
|
|
1768
|
+
className: cn(
|
|
1769
|
+
"flex min-w-0 flex-wrap items-center justify-end gap-2 px-4 sm:px-6",
|
|
1770
|
+
parentNavigation || hasPageHeader ? "pt-2 sm:pt-3" : "pt-4 sm:pt-6"
|
|
1771
|
+
),
|
|
1772
|
+
"data-testid": "app-shell-sub-nav-end-phone"
|
|
1773
|
+
}
|
|
1774
|
+
) : null,
|
|
1761
1775
|
showTabs ? /* @__PURE__ */ jsx(
|
|
1762
1776
|
"div",
|
|
1763
1777
|
{
|
|
@@ -1775,7 +1789,7 @@ function AppShell({
|
|
|
1775
1789
|
isActive,
|
|
1776
1790
|
linkComponent,
|
|
1777
1791
|
label: subNavLabel ?? derived?.current.label ?? "Page sections",
|
|
1778
|
-
end: subNavChannel.hasEnd ? /* @__PURE__ */ jsx("div", { ref: subNavChannel.setEndSlot, className: "flex items-center" }) : void 0
|
|
1792
|
+
end: subNavChannel.hasEnd && !endOnPhone ? /* @__PURE__ */ jsx("div", { ref: subNavChannel.setEndSlot, className: "flex items-center" }) : void 0
|
|
1779
1793
|
}
|
|
1780
1794
|
)
|
|
1781
1795
|
}
|
|
@@ -1855,5 +1869,5 @@ function AppShell({
|
|
|
1855
1869
|
}
|
|
1856
1870
|
|
|
1857
1871
|
export { AppShell, AppShellPageHeader, AppShellSubNavEnd, PageHeader, SubNavTabs, useAppShellSubNav };
|
|
1858
|
-
//# sourceMappingURL=chunk-
|
|
1859
|
-
//# sourceMappingURL=chunk-
|
|
1872
|
+
//# sourceMappingURL=chunk-3FKF2SN4.js.map
|
|
1873
|
+
//# sourceMappingURL=chunk-3FKF2SN4.js.map
|