@godxjp/ui 19.2.0 → 19.4.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/dist/components/data-display/badge.d.ts +26 -2
- package/dist/components/data-display/badge.js +20 -5
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/popover.d.ts +13 -1
- package/dist/components/data-display/popover.js +3 -1
- package/dist/components/data-display/table.d.ts +19 -2
- package/dist/components/data-display/table.js +4 -1
- package/dist/components/data-display/timeline-grid.d.ts +18 -0
- package/dist/components/data-display/timeline-grid.js +222 -0
- package/dist/components/data-entry/cascader.js +4 -6
- package/dist/components/data-entry/checkbox.js +1 -1
- package/dist/components/data-entry/search-select.js +5 -7
- package/dist/components/data-entry/select.js +32 -28
- package/dist/components/data-entry/tree-select.js +4 -6
- package/dist/components/general/inert-background.d.ts +5 -0
- package/dist/components/general/inert-background.js +48 -0
- package/dist/components/layout/auth-shell.d.ts +4 -2
- package/dist/components/layout/auth-shell.js +7 -1
- package/dist/components/layout/centered-shell.d.ts +2 -2
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +2 -1
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/mobile-shell.d.ts +21 -0
- package/dist/components/layout/mobile-shell.js +43 -0
- package/dist/components/layout/sidebar-link.d.ts +1 -1
- package/dist/components/navigation/context-menu.js +13 -9
- package/dist/components/navigation/dropdown-menu.js +17 -13
- package/dist/inertia/index.d.ts +1 -1
- package/dist/lib/variants.d.ts +3 -3
- package/dist/lib/variants.js +1 -0
- package/dist/props/components/data-display.prop.d.ts +72 -0
- package/dist/props/components/data-entry.prop.d.ts +1 -1
- package/dist/props/components/layout.prop.d.ts +93 -6
- package/dist/props/registry.d.ts +113 -2
- package/dist/props/registry.js +155 -1
- package/dist/props/vocabulary/data.prop.d.ts +6 -0
- package/dist/props/vocabulary/index.d.ts +3 -3
- package/dist/props/vocabulary/layout.prop.d.ts +17 -2
- package/dist/props/vocabulary/shared.prop.d.ts +7 -0
- package/dist/styles/badge-layout.css +15 -0
- package/dist/styles/control.css +18 -1
- package/dist/styles/data-display-layout.css +167 -0
- package/dist/styles/layout.css +7 -0
- package/dist/styles/shell-layout.css +148 -0
- package/dist/styles/table-layout.css +23 -4
- package/dist/tokens/components/badge.css +8 -0
- package/dist/tokens/components/control.css +1 -0
- package/dist/tokens/components/data-display.css +20 -0
- package/dist/tokens/components/shell.css +22 -0
- package/dist/tokens/components/table.css +2 -0
- package/docs/SPACING.md +19 -6
- package/docs/charts/compact-bar-trend.tsx +5 -6
- package/docs/data-display/avatar.tsx +7 -9
- package/docs/data-display/badge.tsx +37 -1
- package/docs/data-display/card/index.tsx +6 -4
- package/docs/data-display/carousel.tsx +8 -4
- package/docs/data-display/data-table/examples/approval-queue.tsx +1 -1
- package/docs/data-display/data-table/examples/grid-features.tsx +1 -1
- package/docs/data-display/data-table/index.tsx +1 -1
- package/docs/data-display/permission-matrix.tsx +15 -11
- package/docs/data-display/popover.tsx +2 -1
- package/docs/data-display/scroll-area.tsx +108 -76
- package/docs/data-display/table.tsx +2 -2
- package/docs/data-display/timeline-grid.tsx +119 -0
- package/docs/data-entry/branch-scope-picker.tsx +1 -1
- package/docs/data-entry/calendar.tsx +1 -1
- package/docs/data-entry/checkbox.tsx +1 -1
- package/docs/data-entry/country-picker-recipe.tsx +11 -6
- package/docs/data-entry/form-field/index.tsx +33 -29
- package/docs/data-entry/form-root.tsx +1 -1
- package/docs/data-entry/input-otp.tsx +1 -1
- package/docs/data-entry/password-input.tsx +1 -5
- package/docs/data-entry/select.tsx +7 -7
- package/docs/data-entry/textarea.tsx +3 -3
- package/docs/data-entry/toggle-count.tsx +1 -1
- package/docs/feedback/alert.tsx +1 -1
- package/docs/feedback/banner.tsx +1 -1
- package/docs/feedback/sheet.tsx +112 -102
- package/docs/feedback/skeleton.tsx +2 -2
- package/docs/foundation/colors.tsx +8 -6
- package/docs/foundation/email-tokens.tsx +83 -66
- package/docs/foundation/radius-shadow.tsx +13 -11
- package/docs/general/activity.tsx +1 -1
- package/docs/layout/app-shell.tsx +2 -2
- package/docs/layout/aspect-ratio.tsx +30 -14
- package/docs/layout/auth-account-summary.tsx +1 -1
- package/docs/layout/auth-recovery/examples/mobile-390.tsx +1 -1
- package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -2
- package/docs/layout/auth-shell-context.tsx +1 -1
- package/docs/layout/auth-shell-device.tsx +2 -2
- package/docs/layout/auth-shell-registration.tsx +1 -1
- package/docs/layout/auth-shell.tsx +1 -1
- package/docs/layout/flex.tsx +6 -2
- package/docs/layout/master-detail.tsx +2 -2
- package/docs/layout/mobile-shell.tsx +101 -0
- package/docs/layout/page-container.tsx +15 -7
- package/docs/layout/responsive-grid.tsx +12 -4
- package/docs/layout/separator.tsx +2 -2
- package/docs/layout/service-role-panel.tsx +1 -1
- package/docs/layout/sidebar.tsx +175 -152
- package/docs/layout/split-pane.tsx +45 -28
- package/docs/layout/topbar.tsx +19 -23
- package/docs/navigation/app-setting-picker.tsx +5 -4
- package/docs/navigation/breadcrumb.tsx +12 -5
- package/docs/navigation/context-menu.tsx +10 -4
- package/docs/navigation/filter-bar.tsx +2 -2
- package/docs/navigation/navigation-menu.tsx +89 -96
- package/docs/navigation/pagination.tsx +2 -2
- package/docs/navigation/steps.tsx +13 -11
- package/docs/navigation/tabs.tsx +27 -21
- package/docs/navigation/toolbar.tsx +15 -15
- package/docs/providers/format-date.tsx +2 -2
- package/docs/showcase/acme-portal.tsx +41 -28
- package/docs/showcase/acme-website.tsx +67 -61
- package/docs/showcase/case1-warehouse-dashboard.tsx +46 -31
- package/docs/showcase/case2-employee-me.tsx +33 -36
- package/docs/showcase/case3-approval-workflow.tsx +34 -32
- package/docs/showcase/case4-login.tsx +95 -101
- package/docs/showcase/case5-shift-calendar.tsx +182 -281
- package/docs/showcase/case6-agency-handy.tsx +514 -470
- package/docs/showcase/futurelastic-web.tsx +32 -29
- package/docs/showcase/org-switcher.tsx +20 -13
- package/docs/showcase/permission-matrix.tsx +20 -17
- package/docs/showcase/public-landing.tsx +1 -1
- package/docs/showcase/settings-account-sections.tsx +2 -2
- package/docs/showcase/settings-security-mfa.tsx +3 -3
- package/docs/showcase/table-approval-queue.tsx +1 -1
- package/docs/showcase/table-bulk-actions.tsx +49 -52
- package/docs/showcase/table-conditional-format.tsx +9 -9
- package/docs/showcase/table-crud-list.tsx +4 -4
- package/docs/showcase/table-density.tsx +49 -42
- package/docs/showcase/table-expandable-rows.tsx +112 -100
- package/docs/showcase/table-filter-chips.tsx +78 -71
- package/docs/showcase/table-footer-totals.tsx +30 -23
- package/docs/showcase/table-grouped-subtotals.tsx +31 -25
- package/docs/showcase/table-master-detail.tsx +27 -24
- package/docs/showcase/table-pagination.tsx +34 -27
- package/docs/showcase/table-states.tsx +42 -34
- package/docs/showcase/table-sticky-columns.tsx +11 -7
- package/docs/showcase/table-tree-rows.tsx +22 -15
- package/docs/showcase/table-view-tabs.tsx +12 -14
- package/package.json +7 -7
|
@@ -5,8 +5,7 @@ import { ChevronDown, ChevronRight, ChevronsUpDown, X } from "lucide-react";
|
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
7
|
import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
8
|
-
import {
|
|
9
|
-
import { Button } from "../general/button.js";
|
|
8
|
+
import { controlTriggerClass } from "../../lib/control-styles.js";
|
|
10
9
|
import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
11
10
|
import { ScrollArea } from "../data-display/scroll-area.js";
|
|
12
11
|
import { Checkbox } from "./checkbox.js";
|
|
@@ -177,12 +176,11 @@ function TreeSelectRoot({
|
|
|
177
176
|
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
178
177
|
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
179
178
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
180
|
-
|
|
179
|
+
"button",
|
|
181
180
|
{
|
|
182
181
|
id,
|
|
183
182
|
"data-field": fieldA11y["data-field"] ?? identity["data-field"],
|
|
184
183
|
type: "button",
|
|
185
|
-
variant: "outline",
|
|
186
184
|
role: "combobox",
|
|
187
185
|
"aria-expanded": open,
|
|
188
186
|
"aria-haspopup": "tree",
|
|
@@ -190,9 +188,9 @@ function TreeSelectRoot({
|
|
|
190
188
|
...fieldA11y,
|
|
191
189
|
disabled,
|
|
192
190
|
className: cn(
|
|
193
|
-
|
|
191
|
+
controlTriggerClass,
|
|
192
|
+
"w-full justify-between",
|
|
194
193
|
allowClear && displayKeys.length > 0 && !disabled && "ui-tree-select-trigger-affixed",
|
|
195
|
-
controlOpenRingClass,
|
|
196
194
|
!displayKeys.length && "text-muted-foreground",
|
|
197
195
|
className
|
|
198
196
|
),
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
const TABBABLE = 'a[href], area[href], button, input, select, textarea, iframe, object, embed, details, audio[controls], video[controls], [contenteditable="true"], [tabindex]:not([tabindex^="-"])';
|
|
4
|
+
const owned = /* @__PURE__ */ new Set();
|
|
5
|
+
let observer = null;
|
|
6
|
+
let mounted = 0;
|
|
7
|
+
function sync() {
|
|
8
|
+
for (const el of document.querySelectorAll("[data-aria-hidden]")) {
|
|
9
|
+
if (owned.has(el) || el.hasAttribute("inert")) continue;
|
|
10
|
+
if (el.querySelector(TABBABLE)) {
|
|
11
|
+
el.setAttribute("inert", "");
|
|
12
|
+
owned.add(el);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
for (const el of [...owned]) {
|
|
16
|
+
if (el.isConnected && el.hasAttribute("data-aria-hidden")) continue;
|
|
17
|
+
el.removeAttribute("inert");
|
|
18
|
+
owned.delete(el);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function release() {
|
|
22
|
+
for (const el of owned) el.removeAttribute("inert");
|
|
23
|
+
owned.clear();
|
|
24
|
+
}
|
|
25
|
+
function useInertHiddenBackground() {
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
mounted += 1;
|
|
28
|
+
if (!observer) {
|
|
29
|
+
observer = new MutationObserver(sync);
|
|
30
|
+
observer.observe(document.body, {
|
|
31
|
+
subtree: true,
|
|
32
|
+
attributes: true,
|
|
33
|
+
attributeFilter: ["data-aria-hidden"]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
sync();
|
|
37
|
+
return () => {
|
|
38
|
+
mounted -= 1;
|
|
39
|
+
if (mounted > 0) return;
|
|
40
|
+
observer?.disconnect();
|
|
41
|
+
observer = null;
|
|
42
|
+
release();
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
useInertHiddenBackground
|
|
48
|
+
};
|
|
@@ -3,6 +3,8 @@ export type { AuthShellProp, AuthShellProp as AuthShellProps, } from "../../prop
|
|
|
3
3
|
/**
|
|
4
4
|
* AuthShell — centred auth/login page shell (login · mfa · passkey · device · reset). A top brand
|
|
5
5
|
* bar (banner), a centred `main` that holds the auth `Card`, and an optional footer (contentinfo),
|
|
6
|
-
* over a `min-h-dvh` surface.
|
|
6
|
+
* over a `min-h-dvh` surface. The banner also carries page-level `actions` at its inline end (a
|
|
7
|
+
* locale picker, a theme toggle), and `measure="wide"` opens the content slot to the split login
|
|
8
|
+
* (a brand panel beside the card) that used to have no shell of its own.
|
|
7
9
|
*/
|
|
8
|
-
export declare function AuthShell({ brand, footer, children, variant, preset, density, className, }: AuthShellProp): import("react").JSX.Element;
|
|
10
|
+
export declare function AuthShell({ brand, actions, footer, children, variant, preset, measure, density, className, }: AuthShellProp): import("react").JSX.Element;
|
|
@@ -4,10 +4,12 @@ import { useTranslation } from "../../i18n/use-translation.js";
|
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
function AuthShell({
|
|
6
6
|
brand,
|
|
7
|
+
actions,
|
|
7
8
|
footer,
|
|
8
9
|
children,
|
|
9
10
|
variant = "default",
|
|
10
11
|
preset = "default",
|
|
12
|
+
measure = "default",
|
|
11
13
|
density,
|
|
12
14
|
className
|
|
13
15
|
}) {
|
|
@@ -19,10 +21,14 @@ function AuthShell({
|
|
|
19
21
|
"data-slot": "auth-shell",
|
|
20
22
|
"data-variant": variant,
|
|
21
23
|
"data-preset": preset === "default" ? void 0 : preset,
|
|
24
|
+
"data-measure": measure === "default" ? void 0 : measure,
|
|
22
25
|
"data-density": resolvedDensity,
|
|
23
26
|
className: cn("ui-auth-shell", className),
|
|
24
27
|
children: [
|
|
25
|
-
brand !== void 0 && /* @__PURE__ */
|
|
28
|
+
(brand !== void 0 || actions !== void 0) && /* @__PURE__ */ jsxs("header", { className: "ui-auth-shell-bar", "aria-label": t("layout.authShell.brandLabel"), children: [
|
|
29
|
+
brand,
|
|
30
|
+
actions !== void 0 && /* @__PURE__ */ jsx("div", { className: "ui-auth-shell-bar-actions", children: actions })
|
|
31
|
+
] }),
|
|
26
32
|
/* @__PURE__ */ jsx("main", { className: "ui-auth-shell-main", "aria-label": t("layout.authShell.mainLabel"), children: /* @__PURE__ */ jsx("div", { className: "ui-auth-shell-card", children }) }),
|
|
27
33
|
footer !== void 0 && /* @__PURE__ */ jsx("footer", { className: "ui-auth-shell-footer", "aria-label": t("layout.authShell.footerLabel"), children: footer })
|
|
28
34
|
]
|
|
@@ -5,7 +5,7 @@ export type { CenteredShellProp, CenteredShellProp as CenteredShellProps, } from
|
|
|
5
5
|
* account / self-service, and standalone-settings shape. It fills the gap between the two existing
|
|
6
6
|
* shells: - `AppShell` REQUIRES a sidebar — its padded topbar chrome (`.app-topbar`) is a grid
|
|
7
7
|
* area beside the nav rail, so you cannot get a padded top bar without a rail. - `AuthShell` is
|
|
8
|
-
* the UNAUTHENTICATED root (login/mfa/reset); it centres
|
|
9
|
-
*
|
|
8
|
+
* the UNAUTHENTICATED root (login/mfa/reset); it centres its card VERTICALLY, so a page that
|
|
9
|
+
* scrolls its own content belongs here instead.
|
|
10
10
|
*/
|
|
11
11
|
export declare function CenteredShell({ topbar, footer, children, width, align, preset, className, }: CenteredShellProp): import("react").JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { FlexProp } from "../../props/components/layout.prop.js";
|
|
2
2
|
export type { FlexAlignProp, FlexDirectionProp, FlexJustifyProp, FlexProp, FlexProp as FlexProps, } from "../../props/components/layout.prop.js";
|
|
3
|
-
export declare function Flex({ direction, gap, align, justify, wrap, hideBelow, hideFrom, className, children, ...props }: FlexProp): import("react").JSX.Element;
|
|
3
|
+
export declare function Flex({ as: Element, direction, gap, align, justify, wrap, hideBelow, hideFrom, className, children, ...props }: FlexProp): import("react").JSX.Element;
|
|
@@ -4,6 +4,7 @@ import { mergeAriaIds } from "../../lib/field-a11y.js";
|
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
import { flexGapClass } from "../../lib/variants.js";
|
|
6
6
|
function Flex({
|
|
7
|
+
as: Element = "div",
|
|
7
8
|
direction = "row",
|
|
8
9
|
gap = "md",
|
|
9
10
|
align,
|
|
@@ -30,7 +31,7 @@ function Flex({
|
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
33
|
return /* @__PURE__ */ jsx(
|
|
33
|
-
|
|
34
|
+
Element,
|
|
34
35
|
{
|
|
35
36
|
"data-direction": direction,
|
|
36
37
|
"data-align": align,
|
|
@@ -22,6 +22,9 @@ export { AuthFooter } from "./auth-footer.js";
|
|
|
22
22
|
export type { AuthFooterProp, AuthFooterProps } from "./auth-footer.js";
|
|
23
23
|
export { AuthStack } from "./auth-stack.js";
|
|
24
24
|
export type { AuthStackProps } from "./auth-stack.js";
|
|
25
|
+
export { MobileShell } from "./mobile-shell.js";
|
|
26
|
+
export type { MobileShellProp, MobileShellProps } from "./mobile-shell.js";
|
|
27
|
+
export type { MobileShellHeightProp } from "../../props/vocabulary/index.js";
|
|
25
28
|
export { CenteredShell } from "./centered-shell.js";
|
|
26
29
|
export type { CenteredShellProp, CenteredShellProps } from "./centered-shell.js";
|
|
27
30
|
export type { CenteredShellWidthProp, CenteredShellAlignProp } from "../../props/vocabulary/index.js";
|
|
@@ -10,6 +10,7 @@ import { AccountChip } from "./account-chip.js";
|
|
|
10
10
|
import { AuthAccountSummary } from "./auth-account-summary.js";
|
|
11
11
|
import { AuthFooter } from "./auth-footer.js";
|
|
12
12
|
import { AuthStack } from "./auth-stack.js";
|
|
13
|
+
import { MobileShell } from "./mobile-shell.js";
|
|
13
14
|
import { CenteredShell } from "./centered-shell.js";
|
|
14
15
|
import { ErrorSurface } from "./error-surface.js";
|
|
15
16
|
import { Breadcrumb } from "./breadcrumb.js";
|
|
@@ -38,6 +39,7 @@ export {
|
|
|
38
39
|
Flex,
|
|
39
40
|
LegalDocumentShell,
|
|
40
41
|
MasterDetail,
|
|
42
|
+
MobileShell,
|
|
41
43
|
OrgSwitcher,
|
|
42
44
|
PageContainer,
|
|
43
45
|
ResizableHandle,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { MobileShellProp } from "../../props/components/layout.prop.js";
|
|
2
|
+
export type { MobileShellProp, MobileShellProp as MobileShellProps, } from "../../props/components/layout.prop.js";
|
|
3
|
+
/**
|
|
4
|
+
* MobileShell — the HANDHELD app shell (gh#354 §6): a status band, an app bar, ONE scroll region,
|
|
5
|
+
* a sticky action bar and a bottom tab bar, in that fixed order.
|
|
6
|
+
*
|
|
7
|
+
* The fourth root shell. The other three cannot express a phone app: `AppShell` REQUIRES a sidebar
|
|
8
|
+
* (its bar is a grid area beside the nav rail), `AuthShell` is the UNAUTHENTICATED root and centres
|
|
9
|
+
* a ~24rem card, and `CenteredShell` is a scrolling DOCUMENT — its `main` scrolls the page, which
|
|
10
|
+
* is precisely what a handheld app must not do.
|
|
11
|
+
*
|
|
12
|
+
* SOURCE ORDER IS THE LAYOUT. The bands are a flex column and nothing repositions them, so the DOM
|
|
13
|
+
* order and the reading order are the same order — the accessibility property AppShell has to buy
|
|
14
|
+
* back with grid areas. `actions` therefore comes before `tabBar` in the DOM as well as on screen.
|
|
15
|
+
*
|
|
16
|
+
* i18n: the three landmarks reuse the SHARED shell labels (`layout.appShell.headerLabel` /
|
|
17
|
+
* `.mainLabel` for the bar and the scroll region, `layout.sidebar.ariaLabel` for the tab bar, which
|
|
18
|
+
* IS the app's primary navigation). They are the same strings in all three locales, and a fourth
|
|
19
|
+
* identical copy under `layout.mobileShell.*` would be three files of duplication to keep in sync.
|
|
20
|
+
*/
|
|
21
|
+
export declare function MobileShell({ statusBar, header, children, actions, tabBar, height, className, }: MobileShellProp): import("react").JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from "../../i18n/use-translation.js";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
function MobileShell({
|
|
6
|
+
statusBar,
|
|
7
|
+
header,
|
|
8
|
+
children,
|
|
9
|
+
actions,
|
|
10
|
+
tabBar,
|
|
11
|
+
height = "viewport",
|
|
12
|
+
className
|
|
13
|
+
}) {
|
|
14
|
+
const { t } = useTranslation();
|
|
15
|
+
return /* @__PURE__ */ jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
"data-slot": "mobile-shell",
|
|
19
|
+
"data-height": height === "viewport" ? void 0 : height,
|
|
20
|
+
className: cn("ui-mobile-shell", className),
|
|
21
|
+
children: [
|
|
22
|
+
(statusBar !== void 0 || header !== void 0) && /* @__PURE__ */ jsxs("header", { className: "ui-mobile-shell-chrome", "aria-label": t("layout.appShell.headerLabel"), children: [
|
|
23
|
+
statusBar !== void 0 && /* @__PURE__ */ jsx("div", { className: "ui-mobile-shell-status", children: statusBar }),
|
|
24
|
+
header !== void 0 && /* @__PURE__ */ jsx("div", { className: "ui-mobile-shell-header", children: header })
|
|
25
|
+
] }),
|
|
26
|
+
/* @__PURE__ */ jsx(
|
|
27
|
+
"main",
|
|
28
|
+
{
|
|
29
|
+
className: "ui-mobile-shell-main",
|
|
30
|
+
"aria-label": t("layout.appShell.mainLabel"),
|
|
31
|
+
tabIndex: 0,
|
|
32
|
+
children
|
|
33
|
+
}
|
|
34
|
+
),
|
|
35
|
+
actions !== void 0 && /* @__PURE__ */ jsx("footer", { className: "ui-mobile-shell-actions", children: actions }),
|
|
36
|
+
tabBar !== void 0 && /* @__PURE__ */ jsx("nav", { className: "ui-mobile-shell-tabbar", "aria-label": t("layout.sidebar.ariaLabel"), children: tabBar })
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
MobileShell
|
|
43
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { SidebarLinkComponentProp } from "../../props/components/layout.prop.js";
|
|
3
3
|
/**
|
|
4
|
-
* Adapt a framework router `Link` to {@link SidebarLinkComponentProp}
|
|
4
|
+
* Adapt a framework router `Link` to {@link SidebarLinkComponentProp} — a dependency-free
|
|
5
5
|
* factory, so `@godxjp/ui` still ships ZERO router/framework dependencies.
|
|
6
6
|
*
|
|
7
7
|
* It lives in its own module (imports only React + the prop types) so `@godxjp/ui/inertia` can build
|
|
@@ -4,20 +4,24 @@ import * as React from "react";
|
|
|
4
4
|
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
5
5
|
import { Check, ChevronRight, Circle } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { useInertHiddenBackground } from "../general/inert-background.js";
|
|
7
8
|
const ContextMenu = ContextMenuPrimitive.Root;
|
|
8
9
|
function ContextMenuTrigger(props) {
|
|
9
10
|
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Trigger, { "data-slot": "context-menu-trigger", ...props });
|
|
10
11
|
}
|
|
11
12
|
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
|
12
|
-
const ContextMenuContent = React.forwardRef(({ className, ...props }, ref) =>
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
const ContextMenuContent = React.forwardRef(({ className, ...props }, ref) => {
|
|
14
|
+
useInertHiddenBackground();
|
|
15
|
+
return /* @__PURE__ */ jsx(ContextMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
16
|
+
ContextMenuPrimitive.Content,
|
|
17
|
+
{
|
|
18
|
+
ref,
|
|
19
|
+
"data-slot": "context-menu-content",
|
|
20
|
+
className: cn("ui-context-menu-content", className),
|
|
21
|
+
...props
|
|
22
|
+
}
|
|
23
|
+
) });
|
|
24
|
+
});
|
|
21
25
|
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
22
26
|
const ContextMenuItem = React.forwardRef(({ className, inset, variant = "default", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
23
27
|
ContextMenuPrimitive.Item,
|
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
5
5
|
import { Check, ChevronRight } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { useInertHiddenBackground } from "../general/inert-background.js";
|
|
7
8
|
function DropdownMenu(props) {
|
|
8
9
|
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
9
10
|
}
|
|
@@ -22,19 +23,22 @@ function DropdownMenuRadioGroup(props) {
|
|
|
22
23
|
function DropdownMenuSub(props) {
|
|
23
24
|
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
24
25
|
}
|
|
25
|
-
const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) =>
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
className
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
|
|
27
|
+
useInertHiddenBackground();
|
|
28
|
+
return /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(
|
|
29
|
+
DropdownMenuPrimitive.Content,
|
|
30
|
+
{
|
|
31
|
+
ref,
|
|
32
|
+
"data-slot": "dropdown-menu-content",
|
|
33
|
+
sideOffset,
|
|
34
|
+
className: cn(
|
|
35
|
+
"ui-dropdown-menu-content data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 origin-[var(--radix-dropdown-menu-content-transform-origin)]",
|
|
36
|
+
className
|
|
37
|
+
),
|
|
38
|
+
...props
|
|
39
|
+
}
|
|
40
|
+
) });
|
|
41
|
+
});
|
|
38
42
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
39
43
|
const DropdownMenuItem = React.forwardRef(({ className, inset, variant = "default", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
40
44
|
DropdownMenuPrimitive.Item,
|
package/dist/inertia/index.d.ts
CHANGED
|
@@ -68,7 +68,7 @@ export interface InertiaLinkLike {
|
|
|
68
68
|
children?: ReactNode;
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
|
-
* Bind Inertia's `<Link>` as the Sidebar's row element
|
|
71
|
+
* Bind Inertia's `<Link>` as the Sidebar's row element.
|
|
72
72
|
*
|
|
73
73
|
* The LIBRARY still composes every row — the 16px icon slot, the label, the badge, `data-active` /
|
|
74
74
|
* `aria-current`, the icon-only collapsed rail and its tooltip name — and hands it to the link as
|
package/dist/lib/variants.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ import type { GapProp, PageContainerVariantProp, PageDensityProp } from "../prop
|
|
|
3
3
|
export type Density = PageDensityProp;
|
|
4
4
|
export type StackGap = GapProp;
|
|
5
5
|
export type FlexGap = GapProp;
|
|
6
|
-
export type InlineGap = Exclude<GapProp, "xl">;
|
|
6
|
+
export type InlineGap = Exclude<GapProp, "xl" | "none">;
|
|
7
7
|
export type PageContainerVariant = PageContainerVariantProp;
|
|
8
8
|
export declare const densityClass: Record<PageDensityProp, string>;
|
|
9
9
|
export declare const pageContainerVariantClass: Record<PageContainerVariantProp, string | undefined>;
|
|
10
|
-
export declare const stackGapClass: Record<GapProp, string>;
|
|
11
|
-
export declare const inlineGapClass: Record<
|
|
10
|
+
export declare const stackGapClass: Record<Exclude<GapProp, "none">, string>;
|
|
11
|
+
export declare const inlineGapClass: Record<InlineGap, string>;
|
|
12
12
|
export declare const flexGapClass: Record<GapProp, string>;
|
package/dist/lib/variants.js
CHANGED
|
@@ -137,9 +137,22 @@ export type AvatarPresenceProp = "online" | "away" | "busy" | "offline";
|
|
|
137
137
|
export type AvatarAppearanceProp = "default" | "tinted";
|
|
138
138
|
/** @see Badge */
|
|
139
139
|
export type BadgeProp = {
|
|
140
|
+
/**
|
|
141
|
+
* Render element — `div` (default) or `span` when the chip sits in a phrasing context where a
|
|
142
|
+
* `<div>` is invalid HTML (inside a `<button>` rendered by TabsTrigger/PopoverTrigger/Button,
|
|
143
|
+
* a `<label>`, a `<p>`). Swaps the tag only (gh#354).
|
|
144
|
+
*/
|
|
145
|
+
as?: "div" | "span";
|
|
140
146
|
variant?: "default" | "secondary" | "outline";
|
|
141
147
|
/** Status tones plus a brand `primary` tone (soft brand pill); solid brand = `variant="default"`. */
|
|
142
148
|
tone?: ToneProp | "primary";
|
|
149
|
+
/**
|
|
150
|
+
* The entity's OWN colour (a status, an issue type, a tag) as a CSS colour —
|
|
151
|
+
* DATA, not a semantic tone. Washed into `--badge-tint-surface` rather than
|
|
152
|
+
* filled, because no foreground clears WCAG AA against every colour a picker
|
|
153
|
+
* can produce. Wins over `tone` and over `variant`'s fill.
|
|
154
|
+
*/
|
|
155
|
+
color?: string;
|
|
143
156
|
status?: string;
|
|
144
157
|
icon?: React.ComponentType<{
|
|
145
158
|
className?: string;
|
|
@@ -353,3 +366,62 @@ export type ScrollAreaProp = {
|
|
|
353
366
|
*/
|
|
354
367
|
onAnchoredChange?: (anchored: boolean) => void;
|
|
355
368
|
};
|
|
369
|
+
/**
|
|
370
|
+
* @see TimelineGrid — one COLUMN of the grid (a day, a room, a machine). The label names the
|
|
371
|
+
* column visually AND names the column's event list for assistive technology.
|
|
372
|
+
*/
|
|
373
|
+
export type TimelineGridColumnProp = {
|
|
374
|
+
/** Stable column id — the `columnId` an event points at. */
|
|
375
|
+
id: string;
|
|
376
|
+
/** Column head. Also the accessible name of that column's event list, so keep it text. */
|
|
377
|
+
label: LabelProp;
|
|
378
|
+
/** Secondary line under the head (a date, a capacity, a room number). */
|
|
379
|
+
description?: DescriptionProp;
|
|
380
|
+
/** Marks the column as "now" (today's column): it carries the tint and hosts the `now` marker. */
|
|
381
|
+
current?: boolean;
|
|
382
|
+
};
|
|
383
|
+
/**
|
|
384
|
+
* @see TimelineGrid — one event BLOCK. `start`/`end` are clock times in the column's own day,
|
|
385
|
+
* `"HH:MM"` 24-hour (`"24:00"` = end of day). An `end` at or before `start` continues into the
|
|
386
|
+
* next day (22:00–06:00), and the block is drawn to the end of the window and marked clipped.
|
|
387
|
+
*/
|
|
388
|
+
export type TimelineGridEventProp = {
|
|
389
|
+
/** Stable event id — the React key, and the `data-event-id` on the block. */
|
|
390
|
+
id: string;
|
|
391
|
+
/** Id of the column this event belongs to. An event pointing at no column is not drawn. */
|
|
392
|
+
columnId: string;
|
|
393
|
+
/** Start clock time, `"HH:MM"`. */
|
|
394
|
+
start: string;
|
|
395
|
+
/** End clock time, `"HH:MM"`. At or before `start` = continues into the next day. */
|
|
396
|
+
end: string;
|
|
397
|
+
/** Block title. The block also renders the time range as text, so the range is never colour or position alone. */
|
|
398
|
+
title: TitleProp;
|
|
399
|
+
/** Secondary line inside the block (who is on the shift, a room, a customer). */
|
|
400
|
+
description?: DescriptionProp;
|
|
401
|
+
/** The record's own colour, washed exactly like `Badge color` — decorative, never the only signal. */
|
|
402
|
+
color?: string;
|
|
403
|
+
};
|
|
404
|
+
/** @see TimelineGrid */
|
|
405
|
+
export type TimelineGridProp = {
|
|
406
|
+
/**
|
|
407
|
+
* Accessible name of the grid. Required, and a plain `string`: the grid is a focusable scroll
|
|
408
|
+
* region, so its name has to survive as an `aria-label`.
|
|
409
|
+
*/
|
|
410
|
+
label: Extract<LabelProp, string>;
|
|
411
|
+
/** Columns in render order. */
|
|
412
|
+
columns: readonly TimelineGridColumnProp[];
|
|
413
|
+
/** Events in any order; the grid sorts each column by start time and lays overlaps out side by side. */
|
|
414
|
+
events: readonly TimelineGridEventProp[];
|
|
415
|
+
/** First clock time on the axis, `"HH:MM"`. Defaults to the earliest event, on the hour. */
|
|
416
|
+
start?: string;
|
|
417
|
+
/** Last clock time on the axis, `"HH:MM"`. Defaults to the latest event, on the hour. */
|
|
418
|
+
end?: string;
|
|
419
|
+
/** Hours between hour rules and axis labels. Default `1`. */
|
|
420
|
+
interval?: number;
|
|
421
|
+
/** Current clock time, `"HH:MM"`. Draws the now marker in the columns marked `current`. */
|
|
422
|
+
now?: string;
|
|
423
|
+
/** Block click handler. Its PRESENCE turns every block into a real `button`. */
|
|
424
|
+
onEventSelect?: (event: TimelineGridEventProp) => void;
|
|
425
|
+
className?: ClassNameProp;
|
|
426
|
+
id?: IdProp;
|
|
427
|
+
};
|
|
@@ -106,7 +106,7 @@ export type FormProp = React.FormHTMLAttributes<HTMLFormElement> & {
|
|
|
106
106
|
className?: ClassNameProp;
|
|
107
107
|
};
|
|
108
108
|
/**
|
|
109
|
-
* @see FormField — exactly one of `children` (an interactive control) or `staticText
|
|
109
|
+
* @see FormField — exactly one of `children` (an interactive control) or `staticText`:
|
|
110
110
|
* a read-only VALUE row inside the same Form, styled to match `Descriptions.Item`'s value
|
|
111
111
|
* typography (`text-sm break-all`) byte-for-byte. This is the "mixed read-only + editable fields
|
|
112
112
|
* on one form" case (an immutable name/email row above an editable role Select, for example) —
|