@godxjp/ui 19.6.0 → 20.1.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/README.md +8 -2
- package/dist/app/theme-axes.d.ts +2 -0
- package/dist/app/theme-axes.js +45 -0
- package/dist/components/charts/chart-cartesian.d.ts +2 -1
- package/dist/components/charts/chart-cartesian.js +52 -3
- package/dist/components/charts/chart-category-axis.d.ts +55 -0
- package/dist/components/charts/chart-category-axis.js +93 -0
- package/dist/components/charts/chart-frame.d.ts +10 -1
- package/dist/components/charts/chart-frame.js +19 -3
- package/dist/components/charts/compact-bar-trend.d.ts +1 -1
- package/dist/components/charts/compact-bar-trend.js +2 -0
- package/dist/components/charts/pie-chart.d.ts +1 -1
- package/dist/components/charts/pie-chart.js +12 -1
- package/dist/components/charts/recharts-peer.d.ts +49 -0
- package/dist/components/charts/recharts-peer.js +45 -0
- package/dist/components/data-display/card.d.ts +14 -3
- package/dist/components/data-display/card.js +22 -4
- package/dist/components/data-display/code-block.js +6 -2
- package/dist/components/data-display/collapsible.d.ts +23 -4
- package/dist/components/data-display/collapsible.js +119 -4
- package/dist/components/data-display/data-table.d.ts +39 -4
- package/dist/components/data-display/data-table.js +802 -270
- package/dist/components/data-display/descriptions.d.ts +27 -6
- package/dist/components/data-display/descriptions.js +58 -17
- package/dist/components/data-display/index.d.ts +5 -1
- package/dist/components/data-display/index.js +4 -0
- package/dist/components/data-display/legend.d.ts +15 -0
- package/dist/components/data-display/legend.js +11 -0
- package/dist/components/data-display/list-row.d.ts +10 -1
- package/dist/components/data-display/list-row.js +8 -2
- package/dist/components/data-display/popover.d.ts +60 -7
- package/dist/components/data-display/popover.js +268 -39
- package/dist/components/data-display/progress.d.ts +50 -2
- package/dist/components/data-display/progress.js +57 -9
- package/dist/components/data-display/range-timeline.d.ts +38 -0
- package/dist/components/data-display/range-timeline.js +161 -0
- package/dist/components/data-display/scroll-area.js +13 -2
- package/dist/components/data-display/service-launcher-card.js +10 -10
- package/dist/components/data-display/table.d.ts +11 -3
- package/dist/components/data-display/table.js +48 -18
- package/dist/components/data-display/tree-list.js +4 -9
- package/dist/components/data-entry/calendar.d.ts +2 -2
- package/dist/components/data-entry/calendar.js +79 -33
- package/dist/components/data-entry/cascader.d.ts +1 -1
- package/dist/components/data-entry/cascader.js +188 -24
- package/dist/components/data-entry/checkbox.d.ts +19 -6
- package/dist/components/data-entry/checkbox.js +55 -16
- package/dist/components/data-entry/choice-option.d.ts +1 -1
- package/dist/components/data-entry/color-picker.d.ts +1 -1
- package/dist/components/data-entry/color-picker.js +17 -5
- package/dist/components/data-entry/control-appearance.d.ts +64 -0
- package/dist/components/data-entry/control-appearance.js +39 -0
- package/dist/components/data-entry/control-surface.d.ts +61 -0
- package/dist/components/data-entry/control-surface.js +39 -0
- package/dist/components/data-entry/date-picker.d.ts +1 -1
- package/dist/components/data-entry/date-picker.js +344 -113
- package/dist/components/data-entry/date-range-picker.d.ts +2 -2
- package/dist/components/data-entry/date-range-picker.js +278 -140
- package/dist/components/data-entry/field.js +0 -1
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +39 -4
- package/dist/components/data-entry/form.d.ts +4 -0
- package/dist/components/data-entry/form.js +5 -3
- package/dist/components/data-entry/index.d.ts +7 -3
- package/dist/components/data-entry/index.js +10 -1
- package/dist/components/data-entry/input-otp.d.ts +1 -1
- package/dist/components/data-entry/input.d.ts +12 -34
- package/dist/components/data-entry/input.js +92 -24
- package/dist/components/data-entry/label.d.ts +3 -2
- package/dist/components/data-entry/label.js +23 -10
- package/dist/components/data-entry/month-picker.d.ts +2 -2
- package/dist/components/data-entry/month-picker.js +47 -10
- package/dist/components/data-entry/month-range-picker.d.ts +2 -2
- package/dist/components/data-entry/month-range-picker.js +51 -11
- package/dist/components/data-entry/number-input.d.ts +7 -0
- package/dist/components/data-entry/number-input.js +147 -98
- package/dist/components/data-entry/password-input.d.ts +1 -1
- package/dist/components/data-entry/radio.d.ts +1 -1
- package/dist/components/data-entry/radio.js +61 -13
- package/dist/components/data-entry/search-input.d.ts +1 -1
- package/dist/components/data-entry/search-input.js +16 -2
- package/dist/components/data-entry/search-select.d.ts +2 -2
- package/dist/components/data-entry/search-select.js +209 -78
- package/dist/components/data-entry/select.d.ts +22 -4
- package/dist/components/data-entry/select.js +215 -163
- package/dist/components/data-entry/slider.d.ts +9 -1
- package/dist/components/data-entry/slider.js +87 -9
- package/dist/components/data-entry/switch.d.ts +3 -0
- package/dist/components/data-entry/switch.js +29 -3
- package/dist/components/data-entry/textarea.d.ts +14 -56
- package/dist/components/data-entry/textarea.js +80 -33
- package/dist/components/data-entry/time-picker.d.ts +2 -2
- package/dist/components/data-entry/time-picker.js +333 -109
- package/dist/components/data-entry/time-range-picker.d.ts +5 -0
- package/dist/components/data-entry/time-range-picker.js +89 -0
- package/dist/components/data-entry/transfer.d.ts +1 -1
- package/dist/components/data-entry/transfer.js +99 -31
- package/dist/components/data-entry/tree-select-strategy.d.ts +1 -1
- package/dist/components/data-entry/tree-select.d.ts +1 -1
- package/dist/components/data-entry/tree-select.js +197 -92
- package/dist/components/data-entry/tree-utils.d.ts +1 -1
- package/dist/components/data-entry/tree-utils.js +7 -14
- package/dist/components/data-entry/upload-files.d.ts +2 -0
- package/dist/components/data-entry/upload-files.js +31 -0
- package/dist/components/data-entry/upload-request.d.ts +4 -0
- package/dist/components/data-entry/upload-request.js +53 -0
- package/dist/components/data-entry/upload-types.d.ts +28 -0
- package/dist/components/data-entry/upload-types.js +2 -0
- package/dist/components/data-entry/upload.d.ts +2 -2
- package/dist/components/data-entry/upload.js +482 -117
- package/dist/components/feedback/dialog.d.ts +105 -38
- package/dist/components/feedback/dialog.js +268 -193
- package/dist/components/feedback/overlay-close-focus.d.ts +31 -0
- package/dist/components/feedback/overlay-close-focus.js +31 -0
- package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
- package/dist/components/feedback/sheet.d.ts +53 -11
- package/dist/components/feedback/sheet.js +150 -81
- package/dist/components/feedback/tooltip.d.ts +51 -7
- package/dist/components/feedback/tooltip.js +107 -25
- package/dist/components/general/button.d.ts +1 -1
- package/dist/components/general/button.js +7 -3
- package/dist/components/general/index.d.ts +1 -0
- package/dist/components/general/index.js +2 -0
- package/dist/components/general/logo.d.ts +17 -0
- package/dist/components/general/logo.js +22 -16
- package/dist/components/general/typography.d.ts +3 -0
- package/dist/components/general/typography.js +15 -1
- package/dist/components/general/visually-hidden.d.ts +3 -0
- package/dist/components/general/visually-hidden.js +9 -0
- package/dist/components/layout/app-launcher.d.ts +34 -0
- package/dist/components/layout/app-launcher.js +228 -0
- package/dist/components/layout/app-shell.d.ts +3 -1
- package/dist/components/layout/app-shell.js +69 -12
- package/dist/components/layout/aspect-ratio.js +0 -1
- package/dist/components/layout/auth-divider.js +0 -1
- package/dist/components/layout/breadcrumb.d.ts +14 -2
- package/dist/components/layout/breadcrumb.js +46 -4
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +41 -3
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +5 -1
- package/dist/components/layout/nav-surface.d.ts +26 -0
- package/dist/components/layout/nav-surface.js +17 -0
- package/dist/components/layout/org-switcher.d.ts +5 -1
- package/dist/components/layout/org-switcher.js +25 -4
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +5 -3
- package/dist/components/layout/responsive-grid.d.ts +16 -2
- package/dist/components/layout/responsive-grid.js +29 -2
- package/dist/components/layout/separator.js +0 -1
- package/dist/components/layout/sidebar.js +4 -1
- package/dist/components/layout/split-pane.d.ts +14 -1
- package/dist/components/layout/split-pane.js +26 -13
- package/dist/components/layout/topbar-item.d.ts +3 -0
- package/dist/components/layout/topbar-item.js +19 -5
- package/dist/components/layout/topbar.d.ts +1 -1
- package/dist/components/layout/topbar.js +27 -6
- package/dist/components/navigation/app-setting-picker.js +21 -2
- package/dist/components/navigation/app-setting-toggle.d.ts +16 -0
- package/dist/components/navigation/app-setting-toggle.js +96 -0
- package/dist/components/navigation/dropdown-menu.d.ts +227 -18
- package/dist/components/navigation/dropdown-menu.js +402 -118
- package/dist/components/navigation/index.d.ts +2 -0
- package/dist/components/navigation/index.js +2 -0
- package/dist/components/navigation/pagination-utils.d.ts +2 -1
- package/dist/components/navigation/pagination.d.ts +2 -2
- package/dist/components/navigation/pagination.js +155 -83
- package/dist/components/navigation/steps.d.ts +2 -2
- package/dist/components/navigation/steps.js +29 -4
- package/dist/components/navigation/tabs.d.ts +29 -16
- package/dist/components/navigation/tabs.js +374 -144
- package/dist/components/ui/accordion.d.ts +50 -5
- package/dist/components/ui/accordion.js +239 -33
- package/dist/components/ui/aspect-ratio.d.ts +23 -2
- package/dist/components/ui/aspect-ratio.js +15 -13
- package/dist/components/ui/avatar.d.ts +29 -4
- package/dist/components/ui/avatar.js +111 -25
- package/dist/components/ui/hover-card.d.ts +42 -4
- package/dist/components/ui/hover-card.js +183 -27
- package/dist/components/ui/input-otp.d.ts +26 -28
- package/dist/components/ui/input-otp.js +50 -7
- package/dist/components/ui/label.js +0 -1
- package/dist/components/ui/password-input.d.ts +36 -2
- package/dist/components/ui/password-input.js +27 -7
- package/dist/components/ui/rating.d.ts +25 -0
- package/dist/components/ui/rating.js +67 -27
- package/dist/components/ui/segmented.d.ts +12 -3
- package/dist/components/ui/segmented.js +17 -2
- package/dist/components/ui/separator.d.ts +12 -2
- package/dist/components/ui/separator.js +30 -9
- package/dist/components/ui/tag-input.d.ts +45 -0
- package/dist/components/ui/tag-input.js +109 -27
- package/dist/components/ui/toggle-group.d.ts +50 -5
- package/dist/components/ui/toggle-group.js +79 -20
- package/dist/components/ui/toggle.d.ts +31 -5
- package/dist/components/ui/toggle.js +42 -3
- package/dist/form/form-context.d.ts +29 -0
- package/dist/form/form-context.js +44 -4
- package/dist/form/form-field-array.d.ts +22 -0
- package/dist/form/form-field-array.js +50 -0
- package/dist/form/form-field-control.d.ts +2 -1
- package/dist/form/form-field-control.js +116 -40
- package/dist/form/form-root.d.ts +2 -1
- package/dist/form/form-root.js +142 -23
- package/dist/form/index.d.ts +3 -1
- package/dist/form/index.js +12 -1
- package/dist/i18n/messages/en.json +64 -5
- package/dist/i18n/messages/ja.json +64 -5
- package/dist/i18n/messages/vi.json +64 -5
- package/dist/inertia/index.d.ts +20 -0
- package/dist/inertia/index.js +60 -1
- package/dist/lib/control-styles.d.ts +25 -3
- package/dist/lib/control-styles.js +9 -3
- package/dist/lib/datetime/picker-format.d.ts +8 -0
- package/dist/lib/datetime/picker-format.js +54 -0
- package/dist/lib/slot.d.ts +32 -0
- package/dist/lib/slot.js +22 -0
- package/dist/lib/variants.d.ts +22 -3
- package/dist/lib/variants.js +56 -1
- package/dist/props/components/app.prop.d.ts +25 -1
- package/dist/props/components/charts.prop.d.ts +21 -0
- package/dist/props/components/data-display.prop.d.ts +72 -4
- package/dist/props/components/data-entry.prop.d.ts +718 -46
- package/dist/props/components/form.prop.d.ts +142 -4
- package/dist/props/components/general.prop.d.ts +17 -1
- package/dist/props/components/index.d.ts +3 -3
- package/dist/props/components/layout.prop.d.ts +281 -11
- package/dist/props/components/navigation.prop.d.ts +114 -4
- package/dist/props/registry.d.ts +397 -11
- package/dist/props/registry.js +526 -11
- package/dist/props/vocabulary/content.prop.d.ts +1 -1
- package/dist/props/vocabulary/data.prop.d.ts +179 -1
- package/dist/props/vocabulary/index.d.ts +5 -5
- package/dist/props/vocabulary/interaction.prop.d.ts +68 -3
- package/dist/props/vocabulary/layout.prop.d.ts +57 -1
- package/dist/props/vocabulary/navigation.prop.d.ts +40 -0
- package/dist/props/vocabulary/shared.prop.d.ts +33 -0
- package/dist/styles/badge-layout.css +2 -1
- package/dist/styles/card-layout.css +26 -4
- package/dist/styles/chart-layout.css +15 -0
- package/dist/styles/control.css +657 -15
- package/dist/styles/core.css +5 -2
- package/dist/styles/data-display-layout.css +313 -6
- package/dist/styles/data-entry-layout.css +13 -0
- package/dist/styles/focus-ring.css +4 -0
- package/dist/styles/index.css +5 -2
- package/dist/styles/layout.css +327 -4
- package/dist/styles/navigation-layout.css +227 -0
- package/dist/styles/shell-layout.css +369 -13
- package/dist/styles/table-layout.css +95 -6
- package/dist/styles/text-layout.css +10 -4
- package/dist/tokens/base.css +2 -1
- package/dist/tokens/components/badge.css +1 -0
- package/dist/tokens/components/chart.css +6 -0
- package/dist/tokens/components/control.css +79 -2
- package/dist/tokens/components/data-display.css +20 -0
- package/dist/tokens/components/descriptions.css +11 -0
- package/dist/tokens/components/flex.css +8 -0
- package/dist/tokens/components/navigation.css +55 -0
- package/dist/tokens/components/shell.css +53 -3
- package/dist/tokens/components/table.css +14 -0
- package/dist/tokens/foundation.css +2 -0
- package/dist/tokens/semantic/layout.css +9 -0
- package/docs/COMPONENTS.md +9 -3
- package/docs/CONSUMER-RULES.md +13 -0
- package/docs/DESIGN-AUTHORITY.md +145 -83
- package/docs/DEVELOPMENT.md +4 -3
- package/docs/FORMS.md +151 -6
- package/docs/FRAME-COVERAGE-REPORT.md +32 -17
- package/docs/README.md +15 -15
- package/docs/STANDARDS-vocabulary-tokens.md +1 -1
- package/docs/TESTING.md +15 -6
- package/docs/WHAT-BELONGS-HERE.md +179 -0
- package/docs/charts/cjk-category-axis.tsx +81 -0
- package/docs/data-display/card/index.tsx +22 -0
- package/docs/data-display/data-table/examples/antd-parity.tsx +257 -0
- package/docs/data-display/data-table/index.tsx +23 -0
- package/docs/data-display/descriptions.tsx +41 -0
- package/docs/data-display/legend.tsx +145 -0
- package/docs/data-display/progress.tsx +32 -0
- package/docs/data-display/scroll-area.tsx +31 -25
- package/docs/data-display/table.tsx +104 -45
- package/docs/data-display/timeline.tsx +41 -0
- package/docs/data-entry/date-picker.tsx +85 -0
- package/docs/data-entry/date-range-picker.tsx +26 -0
- package/docs/data-entry/form-dynamic-fields.tsx +199 -0
- package/docs/data-entry/form.tsx +74 -4
- package/docs/data-entry/input-otp.tsx +24 -0
- package/docs/data-entry/input.tsx +46 -1
- package/docs/data-entry/month-range-picker.tsx +1 -1
- package/docs/data-entry/segmented.tsx +1 -1
- package/docs/data-entry/select.tsx +29 -2
- package/docs/data-entry/switch.tsx +41 -0
- package/docs/data-entry/textarea.tsx +38 -0
- package/docs/data-entry/time-picker.tsx +85 -1
- package/docs/data-entry/time-range-picker.tsx +55 -0
- package/docs/data-entry/transfer.tsx +17 -0
- package/docs/data-entry/upload.tsx +56 -12
- package/docs/feedback/sheet.tsx +1 -1
- package/docs/feedback/tooltip.tsx +1 -1
- package/docs/general/activity.tsx +2 -2
- package/docs/general/button/index.tsx +14 -1
- package/docs/general/typography.tsx +14 -1
- package/docs/layout/app-launcher.tsx +151 -0
- package/docs/layout/app-shell-arrangements.tsx +225 -0
- package/docs/layout/app-shell.tsx +11 -0
- package/docs/layout/aspect-ratio.tsx +1 -1
- package/docs/layout/flex.tsx +50 -0
- package/docs/layout/responsive-grid.tsx +21 -1
- package/docs/layout/topbar.tsx +5 -9
- package/docs/navigation/app-setting-picker.tsx +37 -1
- package/docs/navigation/app-setting-toggle.tsx +111 -0
- package/docs/navigation/breadcrumb.tsx +48 -0
- package/docs/navigation/dropdown-menu.tsx +21 -0
- package/docs/navigation/pagination.tsx +52 -0
- package/docs/navigation/steps.tsx +37 -0
- package/docs/navigation/tabs.tsx +97 -1
- package/docs/query/button-refetch.tsx +1 -0
- package/package.json +28 -8
- package/scripts/_agent-setup.mjs +182 -3
- package/scripts/consumer-rule.md +98 -0
- package/scripts/guinea-pig-skill.md +322 -0
- package/scripts/init-guinea-pig.mjs +84 -0
- package/scripts/postinstall.mjs +13 -2
- package/scripts/ui-audit.mjs +351 -37
- /package/dist/tokens/{antd.generated.css → derived.css} +0 -0
|
@@ -3,6 +3,7 @@ import { Text, Heading } from "./typography.js";
|
|
|
3
3
|
import { Logo } from "./logo.js";
|
|
4
4
|
import { Reveal } from "./reveal.js";
|
|
5
5
|
import { Activity } from "./activity.js";
|
|
6
|
+
import { VisuallyHidden } from "./visually-hidden.js";
|
|
6
7
|
export {
|
|
7
8
|
Activity,
|
|
8
9
|
Button,
|
|
@@ -10,5 +11,6 @@ export {
|
|
|
10
11
|
Logo,
|
|
11
12
|
Reveal,
|
|
12
13
|
Text,
|
|
14
|
+
VisuallyHidden,
|
|
13
15
|
buttonVariants
|
|
14
16
|
};
|
|
@@ -45,6 +45,23 @@ export interface LogoProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "
|
|
|
45
45
|
* readable wordmark sits beside it.
|
|
46
46
|
*/
|
|
47
47
|
label?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Mượn thẻ của con làm GỐC của logo thay vì dựng `<span>` — cách để cả cái logo trở thành một
|
|
50
|
+
* LIÊN KẾT (`<a>`, hay `<Link>` của router).
|
|
51
|
+
*
|
|
52
|
+
* Vì sao cần một prop chứ không phải bọc ngoài: `.ui-logo-lockup` là `display: inline-flex`, nên
|
|
53
|
+
* bọc nó trong một `<a>` thường (`display: inline`) đặt lockup lên một line box và phần descender
|
|
54
|
+
* của strut đội thêm vài px vào ô mark — logo bị nhích lên trong thanh trên. Consumer chỉ còn
|
|
55
|
+
* cách viết `className="flex"` lên thẻ `<a>`, thứ `ui-audit` chặn đúng theo luật
|
|
56
|
+
* `no-utility-layout` (đo ở godx-chat, 08/09/2026). Với `asChild`, chính thẻ của consumer MANG
|
|
57
|
+
* `.ui-logo-lockup`, nên không còn phần tử trung gian nào để canh.
|
|
58
|
+
*
|
|
59
|
+
* Đúng MỘT con, và ruột của nó bị bỏ qua: nội dung của logo vẫn do `glyph`/`mark`/`wordmark`
|
|
60
|
+
* quyết định.
|
|
61
|
+
*/
|
|
62
|
+
asChild?: boolean;
|
|
63
|
+
/** Chỉ dùng cùng `asChild`: đúng một phần tử để đi mượn. */
|
|
64
|
+
children?: React.ReactNode;
|
|
48
65
|
}
|
|
49
66
|
/**
|
|
50
67
|
* The band the glyph's ink actually occupies, as the (top edge, bottom edge) of the UNION of every
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { Slot } from "../../lib/slot.js";
|
|
3
4
|
import { cn } from "../../lib/utils.js";
|
|
4
5
|
const X_HEIGHT_TOP = /^[acegmnopqrsuvwxyz]+$/;
|
|
5
6
|
const LATIN_DESCENDER = /[gjpqy]/;
|
|
@@ -83,42 +84,47 @@ const Logo = React.forwardRef(
|
|
|
83
84
|
tone = "primary",
|
|
84
85
|
wordmark,
|
|
85
86
|
label,
|
|
87
|
+
asChild,
|
|
88
|
+
children,
|
|
86
89
|
className,
|
|
87
90
|
...props
|
|
88
91
|
}, ref) => {
|
|
89
92
|
const hasWordmark = wordmark !== void 0 && wordmark !== null && wordmark !== false;
|
|
90
93
|
const identity = { "data-mark": mark, "data-size": size, "data-tone": tone };
|
|
94
|
+
const renderRoot = (rootProps, content) => {
|
|
95
|
+
if (!asChild) {
|
|
96
|
+
return /* @__PURE__ */ jsx("span", { ref, ...rootProps, children: content });
|
|
97
|
+
}
|
|
98
|
+
const borrowed = React.Children.only(children);
|
|
99
|
+
return /* @__PURE__ */ jsx(Slot, { ...rootProps, ref, children: React.cloneElement(borrowed, void 0, content) });
|
|
100
|
+
};
|
|
91
101
|
if (hasWordmark) {
|
|
92
|
-
return
|
|
93
|
-
"span",
|
|
102
|
+
return renderRoot(
|
|
94
103
|
{
|
|
95
|
-
ref,
|
|
96
104
|
"data-slot": "logo-lockup",
|
|
97
105
|
...identity,
|
|
98
106
|
className: cn("ui-logo-lockup", className),
|
|
99
107
|
role: label ? "img" : void 0,
|
|
100
108
|
"aria-label": label,
|
|
101
|
-
...props
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
109
|
+
...props
|
|
110
|
+
},
|
|
111
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
112
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "logo", ...identity, className: "ui-logo", "aria-hidden": "true", children: /* @__PURE__ */ jsx(MarkArtwork, { mark, glyph }) }),
|
|
113
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "logo-wordmark", "data-logotype": true, className: "ui-logo-wordmark", children: wordmark })
|
|
114
|
+
] })
|
|
107
115
|
);
|
|
108
116
|
}
|
|
109
|
-
return
|
|
110
|
-
"span",
|
|
117
|
+
return renderRoot(
|
|
111
118
|
{
|
|
112
|
-
ref,
|
|
113
119
|
"data-slot": "logo",
|
|
114
120
|
...identity,
|
|
115
121
|
className: cn("ui-logo", className),
|
|
116
122
|
role: label ? "img" : void 0,
|
|
117
123
|
"aria-label": label,
|
|
118
124
|
"aria-hidden": label ? void 0 : true,
|
|
119
|
-
...props
|
|
120
|
-
|
|
121
|
-
}
|
|
125
|
+
...props
|
|
126
|
+
},
|
|
127
|
+
/* @__PURE__ */ jsx(MarkArtwork, { mark, glyph })
|
|
122
128
|
);
|
|
123
129
|
}
|
|
124
130
|
);
|
|
@@ -14,7 +14,10 @@ export declare const Text: React.ForwardRefExoticComponent<Omit<React.HTMLAttrib
|
|
|
14
14
|
align?: import("../../props/index.js").TextAlignProp;
|
|
15
15
|
truncate?: boolean;
|
|
16
16
|
clamp?: number;
|
|
17
|
+
whitespace?: import("../../props/index.js").TextWhitespaceProp;
|
|
17
18
|
tabular?: boolean;
|
|
19
|
+
decoration?: "none" | "underline" | "line-through";
|
|
20
|
+
chip?: boolean;
|
|
18
21
|
mono?: boolean;
|
|
19
22
|
htmlFor?: string;
|
|
20
23
|
href?: string;
|
|
@@ -12,7 +12,10 @@ const Text = React.forwardRef(
|
|
|
12
12
|
align,
|
|
13
13
|
truncate,
|
|
14
14
|
clamp,
|
|
15
|
+
whitespace,
|
|
15
16
|
tabular,
|
|
17
|
+
decoration,
|
|
18
|
+
chip,
|
|
16
19
|
mono,
|
|
17
20
|
link,
|
|
18
21
|
className,
|
|
@@ -21,6 +24,7 @@ const Text = React.forwardRef(
|
|
|
21
24
|
...props
|
|
22
25
|
}, ref) => {
|
|
23
26
|
const clampLines = typeof clamp === "number" && Number.isFinite(clamp) && clamp >= 1 ? Math.floor(clamp) : void 0;
|
|
27
|
+
const truncating = truncate === true && clampLines === void 0;
|
|
24
28
|
if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
|
|
25
29
|
if (clamp !== void 0 && clampLines === void 0) {
|
|
26
30
|
console.warn(
|
|
@@ -32,6 +36,11 @@ const Text = React.forwardRef(
|
|
|
32
36
|
"Text: `truncate` and `clamp` are mutually exclusive \u2014 `clamp` takes precedence; drop `truncate`."
|
|
33
37
|
);
|
|
34
38
|
}
|
|
39
|
+
if (whitespace === "pre-wrap" && truncating) {
|
|
40
|
+
console.warn(
|
|
41
|
+
'Text: `truncate` and `whitespace="pre-wrap"` are mutually exclusive \u2014 `truncate` takes precedence (one line, one ellipsis); use `clamp` to keep preserved line breaks and still bound the height.'
|
|
42
|
+
);
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
const typography = {
|
|
37
46
|
"data-slot": "text",
|
|
@@ -40,10 +49,15 @@ const Text = React.forwardRef(
|
|
|
40
49
|
"data-link": link ? "" : void 0,
|
|
41
50
|
"data-weight": weight,
|
|
42
51
|
"data-align": align,
|
|
43
|
-
"data-truncate":
|
|
52
|
+
"data-truncate": truncating ? "" : void 0,
|
|
44
53
|
"data-clamp": clampLines !== void 0 ? "" : void 0,
|
|
54
|
+
// Inert default: `normal` is CSS's own behaviour, so it emits no attribute and there is no
|
|
55
|
+
// `[data-whitespace="normal"]` rule to lose a specificity argument with anything.
|
|
56
|
+
"data-whitespace": whitespace === "pre-wrap" && !truncating ? "pre-wrap" : void 0,
|
|
45
57
|
style: clampLines !== void 0 ? { ...style, "--text-clamp": clampLines } : style,
|
|
46
58
|
"data-tabular": tabular ? "" : void 0,
|
|
59
|
+
"data-decoration": decoration,
|
|
60
|
+
"data-chip": chip ? "" : void 0,
|
|
47
61
|
"data-mono": mono ? "" : void 0,
|
|
48
62
|
className: cn("ui-text", className),
|
|
49
63
|
...props
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
const VisuallyHidden = React.forwardRef(function VisuallyHidden2({ className, ...props }, ref) {
|
|
5
|
+
return /* @__PURE__ */ jsx("span", { ...props, ref, className: cn("sr-only", className) });
|
|
6
|
+
});
|
|
7
|
+
export {
|
|
8
|
+
VisuallyHidden
|
|
9
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { AppLauncherProp } from "../../props/components/layout.prop.js";
|
|
3
|
+
export type { AppLauncherApp, AppLauncherGroup, AppLauncherLabels, AppLauncherProp, AppLauncherProp as AppLauncherProps, } from "../../props/components/layout.prop.js";
|
|
4
|
+
/** Arbitrary `data-*` hooks — the one escape hatch this closed component keeps open. */
|
|
5
|
+
type DataAttributes = {
|
|
6
|
+
[key: `data-${string}`]: string | number | boolean | undefined;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* AppLauncher — the nine-dot app grid in the topbar: the platform's standard way to change app.
|
|
10
|
+
*
|
|
11
|
+
* THE TRIGGER IS A `TopbarItem`, NOT A `Button`. A bar cell is as tall as the bar, its hover IS the
|
|
12
|
+
* bar's surface, and its focus mark is hosted inside it; a `Button variant="ghost"` in the same slot
|
|
13
|
+
* draws a `--control-height` pill floating in a taller strip, with its own hover fill and its own
|
|
14
|
+
* ring drawn around that pill. That was the 20.0.0 correction, and it is why nothing here emits a
|
|
15
|
+
* height: the cell stretches to whatever the bar's height happens to be (`--app-shell-bar-height`,
|
|
16
|
+
* `--topbar-height`, or the coarse-pointer override), so it names none of them.
|
|
17
|
+
*
|
|
18
|
+
* The panel is the SAME responsive contract as `OrgSwitcher`: a desktop popover above
|
|
19
|
+
* `--sheet-responsive-breakpoint-width` and a focus-trapped bottom Sheet at/below it, through the
|
|
20
|
+
* shared `useSheetResponsiveMode()` hook rather than a component-local media query.
|
|
21
|
+
*
|
|
22
|
+
* ## Related — two components this is repeatedly confused with
|
|
23
|
+
*
|
|
24
|
+
* - `ServiceLauncherCard` (data-display) is a launcher tile too, but a PAGE-SIZED one: status,
|
|
25
|
+
* hostname, plan, an action button, a reason it is locked. It belongs on a service-catalogue page,
|
|
26
|
+
* where choosing is a considered act. The tile here is bar-sized — mark plus name, the whole tile
|
|
27
|
+
* one link — because changing app is a reflex. Neither is built out of the other, and a grid of
|
|
28
|
+
* `ServiceLauncherCard`s inside a popover is the wrong component, not a smaller version of this.
|
|
29
|
+
* - `AppShellProp.navRail` says the SAME platform scope as a docked column. Pick ONE: the launcher
|
|
30
|
+
* for a platform with MANY apps where switching is occasional (Google Workspace), the rail for a
|
|
31
|
+
* single product where switching workspace is constant enough to be worth permanent screen width
|
|
32
|
+
* (Slack). Shipping both puts one scope in two places and makes neither authoritative.
|
|
33
|
+
*/
|
|
34
|
+
export declare function AppLauncher({ apps, groups, labels, columns, linkComponent, loading, error, onRetry, responsive, open, onOpenChange, className, ...rest }: AppLauncherProp & Pick<React.ComponentPropsWithoutRef<"button">, "id"> & DataAttributes): React.JSX.Element;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Grip, Loader2, RotateCcw } from "lucide-react";
|
|
5
|
+
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
7
|
+
import {
|
|
8
|
+
Sheet,
|
|
9
|
+
SheetBody,
|
|
10
|
+
SheetContent,
|
|
11
|
+
SheetHeader,
|
|
12
|
+
SheetTrigger,
|
|
13
|
+
useSheetResponsiveMode
|
|
14
|
+
} from "../feedback/sheet.js";
|
|
15
|
+
import { Button } from "../general/button.js";
|
|
16
|
+
import { TopbarItem } from "./topbar-item.js";
|
|
17
|
+
function AppMark({ app }) {
|
|
18
|
+
return /* @__PURE__ */ jsx("span", { className: "ui-app-launcher-mark", "aria-hidden": "true", children: app.icon ?? app.name.trim().charAt(0).toUpperCase() });
|
|
19
|
+
}
|
|
20
|
+
function AppLauncherTile({
|
|
21
|
+
app,
|
|
22
|
+
linkComponent: Link,
|
|
23
|
+
externalHint,
|
|
24
|
+
close
|
|
25
|
+
}) {
|
|
26
|
+
const children = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
27
|
+
/* @__PURE__ */ jsx(AppMark, { app }),
|
|
28
|
+
/* @__PURE__ */ jsx("span", { className: "ui-app-launcher-name", children: app.name }),
|
|
29
|
+
app.external && externalHint != null ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: externalHint }) : null
|
|
30
|
+
] });
|
|
31
|
+
const linkProps = {
|
|
32
|
+
href: app.href,
|
|
33
|
+
className: "ui-app-launcher-tile ui-focus-ring",
|
|
34
|
+
"data-active": app.current ? "true" : void 0,
|
|
35
|
+
"aria-current": app.current ? "page" : void 0,
|
|
36
|
+
onClick: close,
|
|
37
|
+
children
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ jsx("li", { className: "ui-app-launcher-cell", "data-app": app.id, children: app.external || Link == null ? /* @__PURE__ */ jsx(
|
|
40
|
+
"a",
|
|
41
|
+
{
|
|
42
|
+
...linkProps,
|
|
43
|
+
target: app.external ? "_blank" : void 0,
|
|
44
|
+
rel: app.external ? "noreferrer noopener" : void 0
|
|
45
|
+
}
|
|
46
|
+
) : /* @__PURE__ */ jsx(Link, { ...linkProps }) });
|
|
47
|
+
}
|
|
48
|
+
function AppLauncherGrid({
|
|
49
|
+
apps,
|
|
50
|
+
linkComponent,
|
|
51
|
+
externalHint,
|
|
52
|
+
close,
|
|
53
|
+
...props
|
|
54
|
+
}) {
|
|
55
|
+
return /* @__PURE__ */ jsx("ul", { className: "ui-app-launcher-grid", ...props, children: apps.map((app) => /* @__PURE__ */ jsx(
|
|
56
|
+
AppLauncherTile,
|
|
57
|
+
{
|
|
58
|
+
app,
|
|
59
|
+
linkComponent,
|
|
60
|
+
externalHint,
|
|
61
|
+
close
|
|
62
|
+
},
|
|
63
|
+
app.id
|
|
64
|
+
)) });
|
|
65
|
+
}
|
|
66
|
+
function AppLauncherSection({
|
|
67
|
+
label,
|
|
68
|
+
apps,
|
|
69
|
+
linkComponent,
|
|
70
|
+
externalHint,
|
|
71
|
+
close
|
|
72
|
+
}) {
|
|
73
|
+
const labelId = React.useId();
|
|
74
|
+
return /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": labelId, className: "ui-app-launcher-group", children: [
|
|
75
|
+
/* @__PURE__ */ jsx("span", { id: labelId, className: "ui-app-launcher-group-label", children: label }),
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
AppLauncherGrid,
|
|
78
|
+
{
|
|
79
|
+
apps,
|
|
80
|
+
linkComponent,
|
|
81
|
+
externalHint,
|
|
82
|
+
close
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
] });
|
|
86
|
+
}
|
|
87
|
+
function AppLauncherPanel({
|
|
88
|
+
apps,
|
|
89
|
+
groups,
|
|
90
|
+
labels,
|
|
91
|
+
columns,
|
|
92
|
+
linkComponent,
|
|
93
|
+
loading,
|
|
94
|
+
error,
|
|
95
|
+
onRetry,
|
|
96
|
+
close
|
|
97
|
+
}) {
|
|
98
|
+
if (loading) {
|
|
99
|
+
return /* @__PURE__ */ jsxs("div", { className: "ui-app-launcher-state", role: "status", children: [
|
|
100
|
+
/* @__PURE__ */ jsx(Loader2, { className: "ui-app-launcher-spinner", "aria-hidden": "true" }),
|
|
101
|
+
/* @__PURE__ */ jsx("span", { children: labels.loading })
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
104
|
+
if (error != null) {
|
|
105
|
+
return /* @__PURE__ */ jsxs("div", { className: "ui-app-launcher-state", role: "alert", children: [
|
|
106
|
+
/* @__PURE__ */ jsx("span", { children: error }),
|
|
107
|
+
onRetry != null ? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: onRetry, children: [
|
|
108
|
+
/* @__PURE__ */ jsx(RotateCcw, { "aria-hidden": "true" }),
|
|
109
|
+
labels.retry
|
|
110
|
+
] }) : null
|
|
111
|
+
] });
|
|
112
|
+
}
|
|
113
|
+
if (!apps.length && (groups ?? []).every((group) => !group.apps.length)) {
|
|
114
|
+
return /* @__PURE__ */ jsx("div", { className: "ui-app-launcher-state", role: "status", children: /* @__PURE__ */ jsx("span", { children: labels.empty }) });
|
|
115
|
+
}
|
|
116
|
+
return /* @__PURE__ */ jsxs(
|
|
117
|
+
"div",
|
|
118
|
+
{
|
|
119
|
+
className: "ui-app-launcher-panel",
|
|
120
|
+
style: columns == null ? void 0 : { "--app-launcher-columns": String(columns) },
|
|
121
|
+
children: [
|
|
122
|
+
apps.length ? /* @__PURE__ */ jsx(
|
|
123
|
+
AppLauncherGrid,
|
|
124
|
+
{
|
|
125
|
+
apps,
|
|
126
|
+
linkComponent,
|
|
127
|
+
externalHint: labels.externalHint,
|
|
128
|
+
close,
|
|
129
|
+
"aria-label": labels.title
|
|
130
|
+
}
|
|
131
|
+
) : null,
|
|
132
|
+
groups?.map((group) => /* @__PURE__ */ jsx(
|
|
133
|
+
AppLauncherSection,
|
|
134
|
+
{
|
|
135
|
+
label: group.label,
|
|
136
|
+
apps: group.apps,
|
|
137
|
+
linkComponent,
|
|
138
|
+
externalHint: labels.externalHint,
|
|
139
|
+
close
|
|
140
|
+
},
|
|
141
|
+
group.label
|
|
142
|
+
))
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function AppLauncher({
|
|
148
|
+
apps,
|
|
149
|
+
groups,
|
|
150
|
+
labels,
|
|
151
|
+
columns,
|
|
152
|
+
linkComponent,
|
|
153
|
+
loading = false,
|
|
154
|
+
error,
|
|
155
|
+
onRetry,
|
|
156
|
+
responsive = "auto",
|
|
157
|
+
open,
|
|
158
|
+
onOpenChange,
|
|
159
|
+
className,
|
|
160
|
+
...rest
|
|
161
|
+
}) {
|
|
162
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
|
|
163
|
+
const controlled = open !== void 0;
|
|
164
|
+
const resolvedOpen = controlled ? open : uncontrolledOpen;
|
|
165
|
+
const setOpen = React.useCallback(
|
|
166
|
+
(nextOpen) => {
|
|
167
|
+
if (!controlled) {
|
|
168
|
+
setUncontrolledOpen(nextOpen);
|
|
169
|
+
}
|
|
170
|
+
onOpenChange?.(nextOpen);
|
|
171
|
+
},
|
|
172
|
+
[controlled, onOpenChange]
|
|
173
|
+
);
|
|
174
|
+
const compactViewport = useSheetResponsiveMode("auto") === "bottom";
|
|
175
|
+
const sheet = responsive === "sheet" || responsive === "auto" && compactViewport;
|
|
176
|
+
const close = React.useCallback(() => {
|
|
177
|
+
setOpen(false);
|
|
178
|
+
}, [setOpen]);
|
|
179
|
+
const trigger = /* @__PURE__ */ jsx(
|
|
180
|
+
TopbarItem,
|
|
181
|
+
{
|
|
182
|
+
className: cn("ui-app-launcher-trigger", className),
|
|
183
|
+
"aria-label": labels.trigger,
|
|
184
|
+
...rest,
|
|
185
|
+
children: /* @__PURE__ */ jsx(Grip, { "aria-hidden": "true" })
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
const panel = /* @__PURE__ */ jsx(
|
|
189
|
+
AppLauncherPanel,
|
|
190
|
+
{
|
|
191
|
+
apps,
|
|
192
|
+
groups,
|
|
193
|
+
labels,
|
|
194
|
+
columns,
|
|
195
|
+
linkComponent,
|
|
196
|
+
loading,
|
|
197
|
+
error,
|
|
198
|
+
onRetry,
|
|
199
|
+
close
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
if (sheet) {
|
|
203
|
+
return /* @__PURE__ */ jsxs(Sheet, { open: resolvedOpen, onOpenChange: setOpen, children: [
|
|
204
|
+
/* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: trigger }),
|
|
205
|
+
/* @__PURE__ */ jsxs(
|
|
206
|
+
SheetContent,
|
|
207
|
+
{
|
|
208
|
+
responsive: "bottom",
|
|
209
|
+
className: "ui-app-launcher-sheet",
|
|
210
|
+
style: {
|
|
211
|
+
"--sheet-bottom-max-height": "var(--app-launcher-sheet-max-height)"
|
|
212
|
+
},
|
|
213
|
+
children: [
|
|
214
|
+
/* @__PURE__ */ jsx(SheetHeader, { title: labels.title }),
|
|
215
|
+
/* @__PURE__ */ jsx(SheetBody, { children: panel })
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
] });
|
|
220
|
+
}
|
|
221
|
+
return /* @__PURE__ */ jsxs(Popover, { open: resolvedOpen, onOpenChange: setOpen, children: [
|
|
222
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
|
|
223
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "end", className: "ui-app-launcher-popover", "aria-label": labels.title, children: panel })
|
|
224
|
+
] });
|
|
225
|
+
}
|
|
226
|
+
export {
|
|
227
|
+
AppLauncher
|
|
228
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { AppShellProp } from "../../props/components/layout.prop.js";
|
|
3
3
|
export type { AppShellProp, AppShellProp as AppShellProps, } from "../../props/components/layout.prop.js";
|
|
4
|
-
|
|
4
|
+
/** Same rail boundary as shell-layout.css; SSR starts in docked mode. */
|
|
5
|
+
export declare function useAppShellNavigationMode(): "drawer" | "docked";
|
|
6
|
+
export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, breadcrumb, footer, children, sidebarCollapsed, responsiveNavigation, topbarSpan, navRail, navRailLabel, mobileNav, mobileNavLabel, mobileNavOpen, onMobileNavOpenChange, }: AppShellProp): React.JSX.Element;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Menu } from "lucide-react";
|
|
5
|
+
import { useMediaQuery } from "../../lib/hooks.js";
|
|
5
6
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
7
|
import { Button } from "../general/button.js";
|
|
7
8
|
import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from "../feedback/sheet.js";
|
|
9
|
+
import { NavSurfaceProvider } from "./nav-surface.js";
|
|
10
|
+
function useAppShellNavigationMode() {
|
|
11
|
+
return useMediaQuery("(width <= 56.25rem)") ? "drawer" : "docked";
|
|
12
|
+
}
|
|
8
13
|
function AppShell({
|
|
9
14
|
sidebar,
|
|
10
15
|
topbar,
|
|
@@ -17,32 +22,70 @@ function AppShell({
|
|
|
17
22
|
sidebarCollapsed = false,
|
|
18
23
|
responsiveNavigation = "drawer",
|
|
19
24
|
topbarSpan = "content",
|
|
25
|
+
navRail,
|
|
26
|
+
navRailLabel,
|
|
20
27
|
mobileNav,
|
|
21
28
|
mobileNavLabel,
|
|
22
29
|
mobileNavOpen,
|
|
23
30
|
onMobileNavOpenChange
|
|
24
31
|
}) {
|
|
25
32
|
const { t } = useTranslation();
|
|
26
|
-
const
|
|
27
|
-
const
|
|
33
|
+
const navigationMode = useAppShellNavigationMode();
|
|
34
|
+
const hasSidebar = sidebar !== void 0 && sidebar !== null && sidebar !== false;
|
|
35
|
+
const drawerNav = mobileNav !== void 0 ? mobileNav : navRail !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36
|
+
navRail,
|
|
37
|
+
sidebar
|
|
38
|
+
] }) : sidebar;
|
|
39
|
+
const hasDrawer = responsiveNavigation === "drawer" && drawerNav != null && drawerNav !== false;
|
|
40
|
+
const railInDrawer = mobileNav === void 0 && navRail !== void 0;
|
|
28
41
|
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
|
|
29
42
|
const drawerOpen = mobileNavOpen ?? uncontrolledOpen;
|
|
30
43
|
const setDrawerOpen = onMobileNavOpenChange ?? setUncontrolledOpen;
|
|
31
44
|
const handleDrawerClick = (event) => {
|
|
32
45
|
const target = event.target;
|
|
33
46
|
const hit = target.closest("a[href], button, [role='menuitem']");
|
|
34
|
-
if (
|
|
47
|
+
if (!hit) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const opensSomething = hit.hasAttribute("aria-expanded") || hit.hasAttribute("aria-haspopup") || hit.classList.contains("sb-nav-group-trigger");
|
|
51
|
+
if (!opensSomething) {
|
|
35
52
|
setDrawerOpen(false);
|
|
36
53
|
}
|
|
37
54
|
};
|
|
38
55
|
const hasTopbarContent = topbar !== void 0 || topbarLeft !== void 0 || topbarRight !== void 0 || logo !== void 0;
|
|
39
|
-
|
|
40
|
-
|
|
56
|
+
if (process.env.NODE_ENV !== "production" && topbar !== void 0) {
|
|
57
|
+
const ignored = [
|
|
58
|
+
topbarLeft !== void 0 && "topbarLeft",
|
|
59
|
+
topbarRight !== void 0 && "topbarRight"
|
|
60
|
+
].filter(Boolean);
|
|
61
|
+
if (ignored.length > 0) {
|
|
62
|
+
console.warn(
|
|
63
|
+
`AppShell: \`topbar\` \u0111\u01B0\u1EE3c truy\u1EC1n, n\xEAn ${ignored.join(", ")} b\u1ECB b\u1ECF qua v\xE0 KH\xD4NG \u0111\u01B0\u1EE3c v\u1EBD. Ho\u1EB7c b\u1ECF \`topbar\` \u0111\u1EC3 AppShell t\u1EF1 d\u1EF1ng d\u1EA3i t\u1EEB c\xE1c khe kia, ho\u1EB7c \u0111\u1EB7t n\u1ED9i dung \u0111\xF3 v\xE0o trong ch\xEDnh \`topbar\`. (\`logo\` KH\xD4NG n\u1EB1m trong s\u1ED1 n\xE0y \u2014 n\xF3 lu\xF4n \u0111\u01B0\u1EE3c v\u1EBD.)`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const logoInRail = hasSidebar && logo !== void 0 && topbarSpan !== "full";
|
|
68
|
+
const resolvedTopbar = topbar !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "app-topbar-rail", children: [
|
|
69
|
+
!logoInRail && logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: logo }),
|
|
70
|
+
/* @__PURE__ */ jsx("div", { className: "app-topbar-custom", children: topbar })
|
|
71
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "app-topbar-rail", children: [
|
|
72
|
+
!logoInRail && logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: logo }),
|
|
41
73
|
topbarLeft !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-left", children: topbarLeft }),
|
|
42
74
|
/* @__PURE__ */ jsx("div", { className: "app-topbar-spacer" }),
|
|
43
75
|
topbarRight !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-right", children: topbarRight })
|
|
44
76
|
] });
|
|
45
|
-
const rail = /* @__PURE__ */
|
|
77
|
+
const rail = hasSidebar ? /* @__PURE__ */ jsxs("aside", { className: "app-sidebar", "aria-label": t("layout.appShell.sidebarLabel"), children: [
|
|
78
|
+
logoInRail && /* @__PURE__ */ jsx("div", { className: "app-sidebar-logo", children: logo }),
|
|
79
|
+
sidebar
|
|
80
|
+
] }) : null;
|
|
81
|
+
const navRailRegion = navRail === void 0 ? null : /* @__PURE__ */ jsx(
|
|
82
|
+
"aside",
|
|
83
|
+
{
|
|
84
|
+
className: "app-nav-rail",
|
|
85
|
+
"aria-label": navRailLabel ?? t("layout.appShell.navRailLabel"),
|
|
86
|
+
children: navRail
|
|
87
|
+
}
|
|
88
|
+
);
|
|
46
89
|
const bar = !hasTopbarContent && !hasDrawer ? null : /* @__PURE__ */ jsxs("header", { className: "app-topbar ui-scale-fixed", "aria-label": t("layout.appShell.headerLabel"), children: [
|
|
47
90
|
hasDrawer && /* @__PURE__ */ jsxs(Sheet, { open: drawerOpen, onOpenChange: setDrawerOpen, children: [
|
|
48
91
|
/* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
@@ -71,7 +114,10 @@ function AppShell({
|
|
|
71
114
|
{
|
|
72
115
|
className: "app-mobile-nav-body px-[var(--app-shell-mobile-nav-inset)]",
|
|
73
116
|
onClick: handleDrawerClick,
|
|
74
|
-
children:
|
|
117
|
+
children: railInDrawer ? /* @__PURE__ */ jsxs("div", { className: "app-mobile-nav-columns", children: [
|
|
118
|
+
/* @__PURE__ */ jsx("div", { className: "app-mobile-nav-rail", children: navRail }),
|
|
119
|
+
/* @__PURE__ */ jsx(NavSurfaceProvider, { surface: "drawer", children: /* @__PURE__ */ jsx("div", { className: "app-mobile-nav-sections", children: sidebar }) })
|
|
120
|
+
] }) : /* @__PURE__ */ jsx(NavSurfaceProvider, { surface: "drawer", children: drawerNav })
|
|
75
121
|
}
|
|
76
122
|
)
|
|
77
123
|
]
|
|
@@ -84,13 +130,23 @@ function AppShell({
|
|
|
84
130
|
"div",
|
|
85
131
|
{
|
|
86
132
|
className: "app-root",
|
|
87
|
-
"data-collapsed": sidebarCollapsed ? "true" : void 0,
|
|
133
|
+
"data-collapsed": hasSidebar && sidebarCollapsed ? "true" : void 0,
|
|
134
|
+
"data-sidebar": hasSidebar ? void 0 : "none",
|
|
88
135
|
"data-responsive-navigation": responsiveNavigation,
|
|
136
|
+
"data-navigation": navigationMode,
|
|
89
137
|
"data-topbar": hasTopbarContent ? void 0 : "none",
|
|
90
138
|
"data-topbar-span": topbarSpan === "full" ? "full" : void 0,
|
|
139
|
+
"data-nav-rail": navRail !== void 0 ? "" : void 0,
|
|
91
140
|
children: [
|
|
92
|
-
topbarSpan === "full" ?
|
|
93
|
-
|
|
141
|
+
topbarSpan === "full" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
142
|
+
bar,
|
|
143
|
+
navRailRegion,
|
|
144
|
+
rail
|
|
145
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
146
|
+
navRailRegion,
|
|
147
|
+
rail,
|
|
148
|
+
bar
|
|
149
|
+
] }),
|
|
94
150
|
/* @__PURE__ */ jsxs("main", { className: "app-main", "aria-label": t("layout.appShell.mainLabel"), tabIndex: 0, children: [
|
|
95
151
|
breadcrumb !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-breadcrumb", children: breadcrumb }),
|
|
96
152
|
children
|
|
@@ -101,5 +157,6 @@ function AppShell({
|
|
|
101
157
|
);
|
|
102
158
|
}
|
|
103
159
|
export {
|
|
104
|
-
AppShell
|
|
160
|
+
AppShell,
|
|
161
|
+
useAppShellNavigationMode
|
|
105
162
|
};
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import type { ElementType } from "react";
|
|
2
|
-
import type { BreadcrumbProp } from "../../props/vocabulary/navigation.prop.js";
|
|
2
|
+
import type { BreadcrumbItemRenderProp, BreadcrumbProp, BreadcrumbSeparatorProp } from "../../props/vocabulary/navigation.prop.js";
|
|
3
3
|
export type BreadcrumbProps = {
|
|
4
4
|
items: BreadcrumbProp;
|
|
5
5
|
linkComponent?: ElementType;
|
|
6
6
|
/** Override the `<nav>` landmark's accessible name. Defaults to a localized "Breadcrumb". */
|
|
7
7
|
ariaLabel?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Ant Design `separator`. Defaults to the chevron glyph. A string (`"/"`) or any node replaces
|
|
10
|
+
* it; `""` removes it. It is always `aria-hidden` — the trail's structure is carried by the
|
|
11
|
+
* `<ol>`/`<li>`, never by the glyph, so a screen reader never hears "slash" between segments.
|
|
12
|
+
*/
|
|
13
|
+
separator?: BreadcrumbSeparatorProp;
|
|
14
|
+
/**
|
|
15
|
+
* Ant Design `itemRender`. Replaces the anchor/text of ONE segment while this component keeps
|
|
16
|
+
* owning the `<nav>`, the `<ol>`/`<li>`, the separators and `aria-current` — the parts that make
|
|
17
|
+
* the trail a landmark. Use it to hand the trail a router `<Link>` (Inertia, react-router).
|
|
18
|
+
*/
|
|
19
|
+
itemRender?: BreadcrumbItemRenderProp;
|
|
8
20
|
};
|
|
9
|
-
export declare function Breadcrumb({ items, linkComponent: LinkComponent, ariaLabel, }: BreadcrumbProps): import("react").JSX.Element;
|
|
21
|
+
export declare function Breadcrumb({ items, linkComponent: LinkComponent, ariaLabel, separator, itemRender, }: BreadcrumbProps): import("react").JSX.Element;
|