@godxjp/ui 28.7.0 → 28.8.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/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/marquee.d.ts +16 -0
- package/dist/components/data-display/marquee.js +155 -0
- package/dist/components/general/reveal.d.ts +23 -2
- package/dist/components/general/reveal.js +37 -7
- package/dist/components/general/typography.d.ts +4 -1
- package/dist/components/general/typography.js +14 -1
- package/dist/components/layout/affix.d.ts +86 -0
- package/dist/components/layout/affix.js +187 -0
- package/dist/components/layout/index.d.ts +4 -0
- package/dist/components/layout/index.js +4 -0
- package/dist/components/layout/legal-document-shell.js +4 -3
- package/dist/components/layout/masonry.d.ts +74 -0
- package/dist/components/layout/masonry.js +214 -0
- package/dist/components/layout/page-container.js +5 -20
- package/dist/components/navigation/anchor.d.ts +64 -0
- package/dist/components/navigation/anchor.js +284 -0
- package/dist/components/navigation/index.d.ts +4 -0
- package/dist/components/navigation/index.js +4 -0
- package/dist/components/navigation/mega-menu.d.ts +21 -0
- package/dist/components/navigation/mega-menu.js +526 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +517 -0
- package/dist/i18n/messages/ja.json +513 -0
- package/dist/i18n/messages/vi.json +513 -0
- package/dist/lib/hooks.d.ts +68 -0
- package/dist/lib/hooks.js +52 -0
- package/dist/lib/platform.d.ts +14 -0
- package/dist/lib/platform.js +10 -1
- package/dist/lib/utils.d.ts +1 -1
- package/dist/lib/utils.js +3 -2
- package/dist/props/components/data-display.prop.d.ts +95 -1
- package/dist/props/components/general.prop.d.ts +47 -3
- package/dist/props/components/layout.prop.d.ts +194 -0
- package/dist/props/components/navigation.prop.d.ts +263 -0
- package/dist/props/registry.d.ts +359 -4
- package/dist/props/registry.js +472 -3
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +39 -2
- package/dist/styles/control.css +5 -6
- package/dist/styles/data-display-layout.css +2 -1
- package/dist/styles/density.css +4 -0
- package/dist/styles/layout.css +79 -0
- package/dist/styles/motion.css +121 -1
- package/dist/styles/navigation-layout.css +397 -1
- package/dist/styles/shell-layout.css +3 -0
- package/dist/styles/text-layout.css +52 -4
- package/dist/tokens/base.css +5 -0
- package/dist/tokens/components/affix.css +7 -0
- package/dist/tokens/components/anchor.css +17 -0
- package/dist/tokens/components/control.css +3 -3
- package/dist/tokens/components/form.css +1 -1
- package/dist/tokens/components/marquee.css +7 -0
- package/dist/tokens/components/masonry.css +6 -0
- package/dist/tokens/components/mega-menu.css +62 -0
- package/dist/tokens/components/shell.css +3 -0
- package/dist/tokens/foundation.css +11 -0
- package/dist/tokens/semantic/layout.css +7 -0
- package/docs/COMPOSITION-VS-COMPONENT.md +19 -1
- package/docs/DESIGN-AUTHORITY.md +99 -18
- package/docs/FRAME-COVERAGE-REPORT.md +7 -2
- package/docs/data-display/marquee.tsx +254 -0
- package/docs/foundation/_theme-editor-scope.ts +222 -0
- package/docs/foundation/density.tsx +12 -2
- package/docs/foundation/spacing.tsx +5 -0
- package/docs/foundation/theme-editor.tsx +645 -0
- package/docs/general/activity.tsx +65 -0
- package/docs/general/reveal.tsx +290 -22
- package/docs/general/typography.tsx +91 -1
- package/docs/layout/affix.tsx +209 -0
- package/docs/layout/masonry.tsx +291 -0
- package/docs/navigation/anchor.tsx +285 -0
- package/docs/navigation/mega-menu-panel.tsx +86 -0
- package/docs/navigation/mega-menu.tsx +254 -0
- package/docs/roadmap/website-components.md +779 -0
- package/docs/showcase/acme-website.tsx +75 -39
- package/docs/showcase/futurelastic-web.tsx +91 -49
- package/docs/showcase/marketing-page.tsx +885 -0
- package/docs/showcase/table-footer-totals.tsx +12 -2
- package/docs/showcase/theme-customization.tsx +1259 -0
- package/package.json +5 -3
- package/scripts/brand-accent.generated.mjs +27 -0
- package/scripts/ui-audit.mjs +66 -0
- package/scripts/visual-audit-rules.mjs +46 -2
package/dist/lib/hooks.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useLayoutEffect } from "@react-aria/utils";
|
|
2
3
|
import { useEffect, useState } from "react";
|
|
3
4
|
function useDebouncedValue(value, delay = 250) {
|
|
4
5
|
const [debounced, setDebounced] = useState(value);
|
|
@@ -129,9 +130,60 @@ function useScrollsOnAxis(ref, enabled, axis) {
|
|
|
129
130
|
function useScrollsHorizontally(ref, enabled) {
|
|
130
131
|
return useScrollsOnAxis(ref, enabled, "horizontal");
|
|
131
132
|
}
|
|
133
|
+
function scrollParent(el) {
|
|
134
|
+
let node = el?.parentElement ?? null;
|
|
135
|
+
while (node) {
|
|
136
|
+
const overflowY = getComputedStyle(node).overflowY;
|
|
137
|
+
if (overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay") return node;
|
|
138
|
+
node = node.parentElement;
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function useInView(ref, {
|
|
143
|
+
enabled = true,
|
|
144
|
+
once = false,
|
|
145
|
+
amount = "some",
|
|
146
|
+
root = null,
|
|
147
|
+
rootMargin,
|
|
148
|
+
assumeInView = false
|
|
149
|
+
} = {}) {
|
|
150
|
+
const [inView, setInView] = useState(true);
|
|
151
|
+
useLayoutEffect(() => {
|
|
152
|
+
const el = ref.current;
|
|
153
|
+
if (!enabled || !el || typeof IntersectionObserver === "undefined") return void 0;
|
|
154
|
+
const requested = typeof amount === "number" ? amount : amount === "all" ? 1 : 0;
|
|
155
|
+
const box = el.getBoundingClientRect();
|
|
156
|
+
const rootBox = root?.getBoundingClientRect();
|
|
157
|
+
const rootWidth = rootBox?.width ?? window.innerWidth;
|
|
158
|
+
const rootHeight = rootBox?.height ?? window.innerHeight;
|
|
159
|
+
const reachable = box.width > 0 && box.height > 0 ? Math.min(box.width, rootWidth) * Math.min(box.height, rootHeight) / (box.width * box.height) : 1;
|
|
160
|
+
const threshold = Math.min(requested, reachable);
|
|
161
|
+
if (!assumeInView) setInView(false);
|
|
162
|
+
const observer = new IntersectionObserver(
|
|
163
|
+
(entries) => {
|
|
164
|
+
const entry = entries[entries.length - 1];
|
|
165
|
+
if (!entry) return;
|
|
166
|
+
if (entry.isIntersecting && entry.intersectionRatio >= threshold) {
|
|
167
|
+
setInView(true);
|
|
168
|
+
if (once) observer.unobserve(entry.target);
|
|
169
|
+
} else if (!once) {
|
|
170
|
+
setInView(false);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{ root, threshold, ...rootMargin === void 0 ? void 0 : { rootMargin } }
|
|
174
|
+
);
|
|
175
|
+
observer.observe(el);
|
|
176
|
+
return () => {
|
|
177
|
+
observer.disconnect();
|
|
178
|
+
};
|
|
179
|
+
}, [ref, enabled, once, amount, root, rootMargin, assumeInView]);
|
|
180
|
+
return !enabled || inView;
|
|
181
|
+
}
|
|
132
182
|
export {
|
|
183
|
+
scrollParent,
|
|
133
184
|
useControlledLatch,
|
|
134
185
|
useDebouncedValue,
|
|
186
|
+
useInView,
|
|
135
187
|
useIsMobile,
|
|
136
188
|
useMediaQuery,
|
|
137
189
|
useScrollableRegionTabIndex,
|
package/dist/lib/platform.d.ts
CHANGED
|
@@ -8,3 +8,17 @@
|
|
|
8
8
|
* server render therefore describes the Ctrl shortcut.
|
|
9
9
|
*/
|
|
10
10
|
export declare function isApplePlatform(): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Has the user asked for reduced motion (WCAG 2.3.3)?
|
|
13
|
+
*
|
|
14
|
+
* Read at the moment of the gesture rather than subscribed to, because every caller asks the same
|
|
15
|
+
* question at the same instant: "am I allowed to tween THIS scroll / THIS transition". A falsy or
|
|
16
|
+
* unsupported environment — SSR, jsdom, a browser without `matchMedia`, a `matchMedia` that throws
|
|
17
|
+
* on an unknown feature — answers `false`, which is the ordinary animated behaviour rather than a
|
|
18
|
+
* crash.
|
|
19
|
+
*
|
|
20
|
+
* It lives here rather than beside its first caller because it had already been written twice
|
|
21
|
+
* (`src/form/form-root.tsx`, `src/components/layout/legal-document-shell.tsx`) before a third
|
|
22
|
+
* caller needed it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function prefersReducedMotion(): boolean;
|
package/dist/lib/platform.js
CHANGED
|
@@ -4,6 +4,15 @@ function isApplePlatform() {
|
|
|
4
4
|
const platform = data?.platform || navigator.platform || "";
|
|
5
5
|
return /mac|iphone|ipad|ipod/i.test(platform);
|
|
6
6
|
}
|
|
7
|
+
function prefersReducedMotion() {
|
|
8
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
9
|
+
try {
|
|
10
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
7
15
|
export {
|
|
8
|
-
isApplePlatform
|
|
16
|
+
isApplePlatform,
|
|
17
|
+
prefersReducedMotion
|
|
9
18
|
};
|
package/dist/lib/utils.d.ts
CHANGED
package/dist/lib/utils.js
CHANGED
|
@@ -3,8 +3,9 @@ import { twMerge } from "tailwind-merge";
|
|
|
3
3
|
function cn(...inputs) {
|
|
4
4
|
return twMerge(clsx(inputs));
|
|
5
5
|
}
|
|
6
|
-
import { isApplePlatform } from "./platform.js";
|
|
6
|
+
import { isApplePlatform, prefersReducedMotion } from "./platform.js";
|
|
7
7
|
export {
|
|
8
8
|
cn,
|
|
9
|
-
isApplePlatform
|
|
9
|
+
isApplePlatform,
|
|
10
|
+
prefersReducedMotion
|
|
10
11
|
};
|
|
@@ -36,7 +36,7 @@ export type ProseProp = {
|
|
|
36
36
|
className?: ClassNameProp;
|
|
37
37
|
children?: ChildrenProp;
|
|
38
38
|
};
|
|
39
|
-
import type { ActionProp, ClassNameProp, DescriptionProp, IconProp, TitleProp, ColumnDefProp, GetRowIdProp, GetRowLabelProp, OnRowClickProp, OnSelectChangeProp, OnSortChangeProp, OnTableDensityChangeProp, SelectedIdsProp, SortStateProp, TableDensityProp, TablePresetProp, BreakpointProp, DensityProp, ChildrenProp, PendingProp, ToneProp, AvatarShapeProp, HeadingLevelProp, HandlerProp, SizeProp, LabelProp, IdProp, DescriptionsLayoutProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, SortDirectionProp, OnColumnFilterChangeProp, OnRowProp, TableExpandableProp, TableRowSelectionProp, TableScrollProp, TableStickyProp, TableSummaryProp, DisabledProp, OnClickProp, ValueProp, DefaultValueProp, OnValueChangeProp } from "../vocabulary/index.js";
|
|
39
|
+
import type { ActionProp, ClassNameProp, DescriptionProp, IconProp, TitleProp, ColumnDefProp, GetRowIdProp, GetRowLabelProp, OnRowClickProp, OnSelectChangeProp, OnSortChangeProp, OnTableDensityChangeProp, SelectedIdsProp, SortStateProp, TableDensityProp, TablePresetProp, BreakpointProp, DensityProp, ChildrenProp, PendingProp, ToneProp, AvatarShapeProp, HeadingLevelProp, HandlerProp, SizeProp, LabelProp, IdProp, DescriptionsLayoutProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, GapProp, SortDirectionProp, OnColumnFilterChangeProp, OnRowProp, TableExpandableProp, TableRowSelectionProp, TableScrollProp, TableStickyProp, TableSummaryProp, DisabledProp, OnClickProp, ValueProp, DefaultValueProp, OnValueChangeProp } from "../vocabulary/index.js";
|
|
40
40
|
import type { TreeFieldNamesProp, TreeOptionProp } from "./data-entry.prop.js";
|
|
41
41
|
/**
|
|
42
42
|
* One key in a `Legend`: a tone, and the words that tone stands for.
|
|
@@ -1032,3 +1032,97 @@ export type CardTabItemProp = {
|
|
|
1032
1032
|
/** Ant Design `closeIcon` — replaces the default × on this tab's remove button. */
|
|
1033
1033
|
closeIcon?: React.ReactNode;
|
|
1034
1034
|
};
|
|
1035
|
+
/**
|
|
1036
|
+
* @see Marquee — direction of travel, spelled LOGICALLY.
|
|
1037
|
+
*
|
|
1038
|
+
* `react-fast-marquee` says `left | right`; this says `start | end`, the edge the content travels
|
|
1039
|
+
* TOWARDS. `start` is the default because it is the one that follows the reading direction: the
|
|
1040
|
+
* next item arrives from the end edge, exactly as the next word does. Under `dir="rtl"` both
|
|
1041
|
+
* members mirror with the text, so an Arabic page's default marquee travels rightwards with no
|
|
1042
|
+
* prop change at the call site.
|
|
1043
|
+
*
|
|
1044
|
+
* The vertical members of the prior art (`up` / `down`) are NOT ported. A vertical ticker fights
|
|
1045
|
+
* the page scroll and has a different failure mode; porting an axis nobody asked for is how a
|
|
1046
|
+
* single-responsibility component stops being one.
|
|
1047
|
+
*/
|
|
1048
|
+
export type MarqueeDirectionProp = "start" | "end";
|
|
1049
|
+
/**
|
|
1050
|
+
* @see Marquee — travel pace, as an ordinal over the `--marquee-interval` motion token rather than
|
|
1051
|
+
* the prior art's raw `speed` in px/s.
|
|
1052
|
+
*
|
|
1053
|
+
* A px/s number is neither themeable nor width-aware: 50px/s reads as a crawl on a 2560px display
|
|
1054
|
+
* and a sprint on a 390px phone. The ordinal resolves to a duration per SCREENFUL, so the
|
|
1055
|
+
* perceived pace is the same at every width, and a service retunes all of them from one token.
|
|
1056
|
+
*/
|
|
1057
|
+
export type MarqueeSpeedProp = "slow" | "base" | "fast";
|
|
1058
|
+
/**
|
|
1059
|
+
* @see Marquee — a track of content that travels continuously, carrying the WCAG 2.2.2 pause
|
|
1060
|
+
* control that makes it conformant.
|
|
1061
|
+
*
|
|
1062
|
+
* The clone count is MEASURED (content width against viewport width, re-measured on resize) —
|
|
1063
|
+
* the behaviour no CSS-only marquee can have — and the pause control is why this is a component
|
|
1064
|
+
* rather than a snippet. See `src/components/data-display/marquee.tsx` for the full argument and
|
|
1065
|
+
* for what is deliberately not ported from `react-fast-marquee`.
|
|
1066
|
+
*/
|
|
1067
|
+
export type MarqueeProp = Omit<React.HTMLAttributes<HTMLDivElement>, "onPlay" | "onPause" | "children"> & {
|
|
1068
|
+
/**
|
|
1069
|
+
* The row of content — logos, headlines, status chips. Rendered ONCE for real; every further
|
|
1070
|
+
* copy that fills the track is an `aria-hidden` + `inert` clone, so the accessibility tree and
|
|
1071
|
+
* the tab order see the content exactly once however wide the viewport is.
|
|
1072
|
+
*/
|
|
1073
|
+
children?: ChildrenProp;
|
|
1074
|
+
/**
|
|
1075
|
+
* Whether the track is moving. The controlled member of the triad — pass it with
|
|
1076
|
+
* `onPlayChange`.
|
|
1077
|
+
*
|
|
1078
|
+
* WCAG 2.2.2 is satisfied by the built-in control whichever way this is driven; a controlled
|
|
1079
|
+
* `play` exists so one "stop all motion" switch can halt every marquee on a page at once.
|
|
1080
|
+
*/
|
|
1081
|
+
play?: boolean;
|
|
1082
|
+
/**
|
|
1083
|
+
* Uncontrolled initial state. Default `true`.
|
|
1084
|
+
*
|
|
1085
|
+
* WebAIM recommends animated content be paused by default where the motion is not the point of
|
|
1086
|
+
* the screen (https://webaim.org/techniques/carousels/); `defaultPlay={false}` is that screen,
|
|
1087
|
+
* and it still starts from the built-in control.
|
|
1088
|
+
*/
|
|
1089
|
+
defaultPlay?: boolean;
|
|
1090
|
+
/** Fires on every transition, from the built-in control or from a controlled write. */
|
|
1091
|
+
onPlayChange?: (play: boolean) => void;
|
|
1092
|
+
/** Edge the content travels towards. Default `start` — the reading direction. */
|
|
1093
|
+
direction?: MarqueeDirectionProp;
|
|
1094
|
+
/** Pace ordinal over `--marquee-interval`. Default `base`. */
|
|
1095
|
+
speed?: MarqueeSpeedProp;
|
|
1096
|
+
/**
|
|
1097
|
+
* Space between items AND between copies, as a token step. Defaults to the
|
|
1098
|
+
* `--marquee-gap-inline` token, so a service sets the resting rhythm once.
|
|
1099
|
+
*/
|
|
1100
|
+
gap?: GapProp;
|
|
1101
|
+
/**
|
|
1102
|
+
* Also pause while the pointer is over the track. Default `false`.
|
|
1103
|
+
*
|
|
1104
|
+
* An ADDITION, never the mechanism: a keyboard user never hovers, so hover-to-pause alone is
|
|
1105
|
+
* exactly the WCAG 2.2.2 failure (technique F16) the prior art ships. Focus inside the track
|
|
1106
|
+
* always pauses it, whatever this says, because a link that is moving cannot be activated.
|
|
1107
|
+
*/
|
|
1108
|
+
pauseOnHover?: boolean;
|
|
1109
|
+
/**
|
|
1110
|
+
* Fade both edges over `--marquee-mask-width` so items enter and leave instead of being cut.
|
|
1111
|
+
* Default `false`. A mask, not the prior art's opaque `gradientColor` — a gradient painted in a
|
|
1112
|
+
* fixed colour cannot follow a themed or dark background.
|
|
1113
|
+
*/
|
|
1114
|
+
fade?: boolean;
|
|
1115
|
+
/**
|
|
1116
|
+
* Names the CONTENT, not the button: "partner logos", "お知らせ". The control's accessible name
|
|
1117
|
+
* is built from it ("Pause scrolling: partner logos"), so a page with several tracks can tell
|
|
1118
|
+
* them apart by voice as well as by eye.
|
|
1119
|
+
*
|
|
1120
|
+
* It is not the whole button name on purpose. A caller string would read the same in both
|
|
1121
|
+
* states, and a control that says "pause" while it resumes is worse than an unnamed one; the
|
|
1122
|
+
* verb stays the component's, and the catalog composes the two in each locale's own order.
|
|
1123
|
+
* Optional: omitted, the control takes the localized verb alone. A non-string node cannot be an
|
|
1124
|
+
* `aria-label`, so it is ignored.
|
|
1125
|
+
*/
|
|
1126
|
+
label?: LabelProp;
|
|
1127
|
+
className?: ClassNameProp;
|
|
1128
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Foundation component prop types — @see docs/COMPONENTS.md#foundation */
|
|
2
2
|
import type * as React from "react";
|
|
3
|
-
import type { ActivityAnnounceProp, ActivityVariantProp, AsChildProp, ButtonSizeProp, ButtonVariantProp, ChildrenProp, ClassNameProp, DescriptionProp, DisabledProp, FontWeightProp, HeadingLevelProp, IconSizeProp, IdProp, LabelProp, OnClickProp, OnOpenChangeProp, OpenProp, PendingProp, RevealDelayProp, ShapeProp, SizeProp, TextAlignProp, TextSizeProp, TextToneProp, TextWhitespaceProp, TitleLevelProp, TypographyActionsConfigProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyTypeProp } from "../vocabulary/index.js";
|
|
3
|
+
import type { ActivityAnnounceProp, ActivityVariantProp, AsChildProp, ButtonSizeProp, ButtonVariantProp, ChildrenProp, ClassNameProp, DescriptionProp, DisabledProp, FontWeightProp, HeadingLevelProp, IconSizeProp, IdProp, InViewAmountProp, LabelProp, OnClickProp, OnOpenChangeProp, OpenProp, PendingProp, RevealDelayProp, RevealTriggerProp, ShapeProp, SizeProp, TextAlignProp, TextSizeProp, TextToneProp, TextWhitespaceProp, TitleLevelProp, TypographyActionsConfigProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyTypeProp } from "../vocabulary/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* @see Text — typographic primitive; replaces hand-rolled `<span className="text-[13px] …">`.
|
|
6
6
|
*
|
|
@@ -87,10 +87,24 @@ export type TextProp = Omit<React.HTMLAttributes<HTMLElement>, "color"> & Omit<T
|
|
|
87
87
|
rel?: string;
|
|
88
88
|
download?: React.AnchorHTMLAttributes<HTMLAnchorElement>["download"];
|
|
89
89
|
};
|
|
90
|
-
/** @see Heading — h1..h4 sized from the `--heading-h*` tokens. */
|
|
90
|
+
/** @see Heading — h1..h4 sized from the `--heading-h*` tokens, or from `size` when one is given. */
|
|
91
91
|
export type HeadingProp = Omit<React.HTMLAttributes<HTMLHeadingElement>, "color"> & {
|
|
92
92
|
/** Heading level — sets size token AND the semantic element (override the element with `as`). */
|
|
93
93
|
level?: HeadingLevelProp;
|
|
94
|
+
/**
|
|
95
|
+
* Visual size, overriding the step `level` would have taken — the SAME ten-step ladder
|
|
96
|
+
* `Text size` reads, so a headline and a stat figure beside it are one step name apart rather
|
|
97
|
+
* than a lookup between two ramps.
|
|
98
|
+
*
|
|
99
|
+
* `level` still owns the document outline, and that separation is the point (gh#826). The
|
|
100
|
+
* enterprise heading ramp tops out at `--heading-h1` ≈ 20px by deliberate 渋み restraint, so a
|
|
101
|
+
* marketing hero had no way to be both a real `<h1>` and 54px: the display tokens existed,
|
|
102
|
+
* nothing public reached them, and every marketing page wrote its own class instead. Now it is
|
|
103
|
+
* `<Heading level={1} size="5xl">`, and no admin screen's `<h1>` moves.
|
|
104
|
+
*
|
|
105
|
+
* Omit it and `level` decides, exactly as before — this is an override, not a second default.
|
|
106
|
+
*/
|
|
107
|
+
size?: TextSizeProp;
|
|
94
108
|
as?: "h1" | "h2" | "h3" | "h4" | "div";
|
|
95
109
|
tone?: TextToneProp;
|
|
96
110
|
align?: TextAlignProp;
|
|
@@ -284,10 +298,20 @@ export type ButtonProp = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
|
284
298
|
};
|
|
285
299
|
/**
|
|
286
300
|
* @see Reveal — entrance-motion primitive (staggered fade-up). Wraps content in a real element
|
|
287
|
-
* that animates in
|
|
301
|
+
* that animates in reading the DS motion tokens (`--duration-slow`, `--ease-emphasized`,
|
|
288
302
|
* `--reveal-distance`), replacing hand-rolled `@keyframes` + `.app-reveal`/`.d1..d6` classes.
|
|
289
303
|
* Honours `prefers-reduced-motion` — the animation is dropped and content stays fully visible with
|
|
290
304
|
* no layout shift.
|
|
305
|
+
*
|
|
306
|
+
* `on` moves the TRIGGER and nothing else (gh#829): `"mount"` is the historical behaviour, `"view"`
|
|
307
|
+
* waits for the viewport. There is deliberately no second `ScrollReveal` component — same
|
|
308
|
+
* animation, same tokens, same reduced-motion contract, one extra prop.
|
|
309
|
+
*
|
|
310
|
+
* **Visibility is never gated on the observer.** The resting state in the stylesheet is the FINAL,
|
|
311
|
+
* fully visible one; only a mounted component that has attached a live `IntersectionObserver` and
|
|
312
|
+
* measured the element as still outside the viewport writes the hidden state. A server render,
|
|
313
|
+
* jsdom, a browser without `IntersectionObserver` and `prefers-reduced-motion: reduce` therefore
|
|
314
|
+
* all show the content — a reveal that never reveals is the worst outcome available here.
|
|
291
315
|
*/
|
|
292
316
|
export type RevealProp = React.HTMLAttributes<HTMLDivElement> & {
|
|
293
317
|
/** Child content to reveal on enter. */
|
|
@@ -297,6 +321,26 @@ export type RevealProp = React.HTMLAttributes<HTMLDivElement> & {
|
|
|
297
321
|
* `--reveal-stagger-step` of delay so sibling reveals cascade.
|
|
298
322
|
*/
|
|
299
323
|
delay?: RevealDelayProp;
|
|
324
|
+
/**
|
|
325
|
+
* What starts the entrance. Default `"mount"` — today's behaviour, so nothing moves for existing
|
|
326
|
+
* consumers. `"view"` holds the entrance until the element reaches the viewport.
|
|
327
|
+
*/
|
|
328
|
+
on?: RevealTriggerProp;
|
|
329
|
+
/**
|
|
330
|
+
* `on="view"` only. Reveal once and never re-hide. Default `true` — a `Reveal` is a ONE-SHOT
|
|
331
|
+
* entrance under either trigger, so this keeps `"view"` semantically identical to `"mount"`.
|
|
332
|
+
* (Motion's `useInView`, where this prop comes from, defaults it to `false`; that is the neutral
|
|
333
|
+
* reading for a general-purpose observer, not for an entrance primitive.) `false` re-plays the
|
|
334
|
+
* entrance on every re-entry.
|
|
335
|
+
*/
|
|
336
|
+
once?: boolean;
|
|
337
|
+
/**
|
|
338
|
+
* `on="view"` only. How much of the element must be visible before it reveals — Motion's
|
|
339
|
+
* `amount`, unchanged: `"some"` (default, any pixel) | `"all"` | an explicit `0..1` ratio.
|
|
340
|
+
* `"all"` is clamped to the most the element's own box can show inside the viewport, so a
|
|
341
|
+
* full-height section still reveals.
|
|
342
|
+
*/
|
|
343
|
+
amount?: InViewAmountProp;
|
|
300
344
|
/**
|
|
301
345
|
* Merge the reveal behaviour onto the single child element (Radix `Slot`) instead of rendering a
|
|
302
346
|
* wrapper `<div>` — use when an extra box would break a grid/flex layout. Default `false`.
|
|
@@ -1657,3 +1657,197 @@ export type DraggablePanelProp = Omit<React.HTMLAttributes<HTMLElement>, "title"
|
|
|
1657
1657
|
disabled?: DisabledProp;
|
|
1658
1658
|
className?: ClassNameProp;
|
|
1659
1659
|
};
|
|
1660
|
+
/**
|
|
1661
|
+
* Masonry column count — Ant Design `Masonry columns`, in this library's responsive shape.
|
|
1662
|
+
*
|
|
1663
|
+
* A plain number is that many columns at every width. The object form is the step map
|
|
1664
|
+
* `Flex direction` already uses — `base` plus `sm` 40rem · `md` 48rem · `lg` 64rem · `xl` 80rem —
|
|
1665
|
+
* and each omitted step falls back to the widest one below it, exactly as the `--flex-direction-*`
|
|
1666
|
+
* cascade does in CSS.
|
|
1667
|
+
*
|
|
1668
|
+
* **antd spells the steps `xs sm md lg xl xxl` and this does not.** The two ends are the
|
|
1669
|
+
* divergence: antd's `xs` is its mobile-first floor, which is this library's `base` (a second
|
|
1670
|
+
* spelling of one axis is what `check:prop-vocabulary` exists to prevent), and `xxl` has no step
|
|
1671
|
+
* here at all. An `xs` or `xxl` key is therefore never silently dropped — TypeScript rejects it as
|
|
1672
|
+
* an excess property, and a value that reaches the component anyway (a plain-JS caller, a widened
|
|
1673
|
+
* object) is named in a development-only warning. See docs/DESIGN-AUTHORITY.md.
|
|
1674
|
+
* @see Masonry
|
|
1675
|
+
*/
|
|
1676
|
+
export type MasonryColumnsProp = number | Partial<Record<"base" | BreakpointProp, number>>;
|
|
1677
|
+
/**
|
|
1678
|
+
* Masonry spacing — Ant Design `Masonry gutter`, on this library's `GapProp` scale.
|
|
1679
|
+
*
|
|
1680
|
+
* One step applies to both axes; the tuple is antd's `[Gap, Gap]`, i.e. `[inline, block]`.
|
|
1681
|
+
* The value is a TOKEN STEP rather than antd's raw pixel number, so a masonry breathes with
|
|
1682
|
+
* `--scaling` (density) like every other gap in the package.
|
|
1683
|
+
* @see Masonry
|
|
1684
|
+
*/
|
|
1685
|
+
export type MasonryGapProp = GapProp | [GapProp, GapProp];
|
|
1686
|
+
/**
|
|
1687
|
+
* One tile handed to `Masonry items` — Ant Design `MasonryItem`, field for field.
|
|
1688
|
+
* @see Masonry
|
|
1689
|
+
*/
|
|
1690
|
+
export type MasonryItemProp<TData = unknown> = {
|
|
1691
|
+
/** Identity of the tile across re-orders and re-measures. Ant Design `MasonryItem.key`. */
|
|
1692
|
+
key: React.Key;
|
|
1693
|
+
/** The tile itself. Wins over `itemRender`, as in Ant Design. */
|
|
1694
|
+
children?: ReactNode;
|
|
1695
|
+
/**
|
|
1696
|
+
* Pin the tile to a column INDEX (0-based) instead of letting it fall into the shortest one.
|
|
1697
|
+
* Ant Design `MasonryItem.column`, clamped to the live column count.
|
|
1698
|
+
*/
|
|
1699
|
+
column?: number;
|
|
1700
|
+
/**
|
|
1701
|
+
* Declared block size, in pixels, used INSTEAD of measuring the tile.
|
|
1702
|
+
*
|
|
1703
|
+
* antd declares and documents this field and then never reads it — its layout is measured from
|
|
1704
|
+
* `getBoundingClientRect()` alone, and all six of its demos carry their heights in `data`. A
|
|
1705
|
+
* prop that does nothing is worse than an absent one, so here the documented meaning is the
|
|
1706
|
+
* real one: a finite `height` sizes the tile and skips its measurement, which is what makes a
|
|
1707
|
+
* first paint (and an SSR render) land in the right place.
|
|
1708
|
+
*/
|
|
1709
|
+
height?: number;
|
|
1710
|
+
/** Arbitrary payload handed back to `itemRender` and `onLayoutChange`. Ant Design `MasonryItem.data`. */
|
|
1711
|
+
data?: TData;
|
|
1712
|
+
};
|
|
1713
|
+
/** One row of the `onLayoutChange` payload: the item, plus the column it landed in. @see Masonry */
|
|
1714
|
+
export type MasonryLayoutEntryProp<TData = unknown> = MasonryItemProp<TData> & {
|
|
1715
|
+
/** 0-based column index the item occupies. */
|
|
1716
|
+
column: number;
|
|
1717
|
+
};
|
|
1718
|
+
/**
|
|
1719
|
+
* @see Masonry — Ant Design's `Masonry` (6.0.0): tiles of unequal height packed into columns.
|
|
1720
|
+
*
|
|
1721
|
+
* Ant's own surface, field for field: `items`, `itemRender`, `columns`, `fresh`, `onLayoutChange`.
|
|
1722
|
+
* The three named divergences (`gap` for `gutter`, the breakpoint step names, and the absence of
|
|
1723
|
+
* `classNames`/`styles`) each carry their reason at the field, and all three are recorded in
|
|
1724
|
+
* docs/DESIGN-AUTHORITY.md.
|
|
1725
|
+
*/
|
|
1726
|
+
export type MasonryProp<TData = unknown> = {
|
|
1727
|
+
/** The tiles, in READING order — which is also DOM order. Ant Design `items`. */
|
|
1728
|
+
items?: MasonryItemProp<TData>[];
|
|
1729
|
+
/**
|
|
1730
|
+
* Renders a tile that carries no `children`. Receives the item plus its live `index` and
|
|
1731
|
+
* `column`, exactly as Ant Design does. Ant Design `itemRender`.
|
|
1732
|
+
*/
|
|
1733
|
+
itemRender?: (item: MasonryItemProp<TData> & {
|
|
1734
|
+
index: number;
|
|
1735
|
+
column: number;
|
|
1736
|
+
}) => ReactNode;
|
|
1737
|
+
/** Column count, fixed or per step. Ant Design `columns`, default `3`. */
|
|
1738
|
+
columns?: MasonryColumnsProp;
|
|
1739
|
+
/**
|
|
1740
|
+
* Spacing between tiles, on the `GapProp` scale. Ant Design calls this `gutter` and defaults it
|
|
1741
|
+
* to `0`; the name here is `gap` because this package already owns that axis under that name
|
|
1742
|
+
* (`Flex`, `ResponsiveGrid`, `AuthStack`, …) and `check:prop-vocabulary` maps a field called
|
|
1743
|
+
* `gap` to `GapProp`. The antd default is kept: omitted means `"none"`.
|
|
1744
|
+
*/
|
|
1745
|
+
gap?: MasonryGapProp;
|
|
1746
|
+
/**
|
|
1747
|
+
* NOT A PROP — Ant Design's name for `gap`, kept in the type so that arriving from antd's docs
|
|
1748
|
+
* is a compile error that says where to go, rather than a tile grid with no spacing and no
|
|
1749
|
+
* complaint. Passing it also warns in development.
|
|
1750
|
+
*
|
|
1751
|
+
* @deprecated Ant Design spells this `gutter`; in `@godxjp/ui` it is `gap`, and it takes a
|
|
1752
|
+
* `GapProp` token step (`"sm"`, `4`, `["md", "lg"]`) rather than antd's raw pixel number.
|
|
1753
|
+
*/
|
|
1754
|
+
gutter?: never;
|
|
1755
|
+
/**
|
|
1756
|
+
* Keep watching every tile's own size, not just the container's.
|
|
1757
|
+
*
|
|
1758
|
+
* Ant Design `fresh`, and it means exactly one thing in Ant's source: each tile is wrapped in
|
|
1759
|
+
* its own `ResizeObserver` so a tile that changes height on its own — an image decoding, a
|
|
1760
|
+
* "show more" expanding, a chart settling — re-packs the columns. Off (the default), the layout
|
|
1761
|
+
* is re-measured only when the CONTAINER resizes or a descendant `load`/`error` event fires, so
|
|
1762
|
+
* a tile that grows in place leaves a gap or overlaps its neighbour until something else moves.
|
|
1763
|
+
*/
|
|
1764
|
+
fresh?: boolean;
|
|
1765
|
+
/**
|
|
1766
|
+
* Fires when the column assignment changes. Ant Design `onLayoutChange`.
|
|
1767
|
+
*
|
|
1768
|
+
* Ant's own documented type is `({ key, column }[]) => void`, but its implementation hands back
|
|
1769
|
+
* the WHOLE item spread with `column` added — so `data` and `children` come with it. This ports
|
|
1770
|
+
* the implementation (a superset of the documented payload) rather than the narrower doc.
|
|
1771
|
+
*
|
|
1772
|
+
* It fires only once every tile has a resolved position and the count matches `items`, and is
|
|
1773
|
+
* deduped: an identical [item, column] list does not call it again.
|
|
1774
|
+
*/
|
|
1775
|
+
onLayoutChange?: (layout: MasonryLayoutEntryProp<TData>[]) => void;
|
|
1776
|
+
id?: IdProp;
|
|
1777
|
+
className?: ClassNameProp;
|
|
1778
|
+
};
|
|
1779
|
+
/**
|
|
1780
|
+
* The scroll box an `Affix` pins against — Ant Design `Affix target`, shape for shape, and the
|
|
1781
|
+
* same lazy getter `FloatButton.BackTop target` already spells here.
|
|
1782
|
+
*
|
|
1783
|
+
* It is a FUNCTION and not an element because the element does not exist on the render that
|
|
1784
|
+
* declares it: the caller writes `target={() => scrollRef.current}` and the component calls it
|
|
1785
|
+
* after mount. `window` (the default) means the document viewport.
|
|
1786
|
+
* @see Affix
|
|
1787
|
+
*/
|
|
1788
|
+
export type AffixTargetProp = () => Window | HTMLElement | null;
|
|
1789
|
+
/**
|
|
1790
|
+
* @see Affix — Ant Design's `Affix`: pin an element to its scrollport once the page scrolls past
|
|
1791
|
+
* it, and SAY SO, which is the whole difference from `position: sticky`.
|
|
1792
|
+
*
|
|
1793
|
+
* antd's surface, field for field — `offsetTop`, `offsetBottom`, `target`, `onChange` — with the
|
|
1794
|
+
* two physical offsets renamed to their logical axis (see the fields). `onChange` keeps antd's
|
|
1795
|
+
* name and antd's payload: it is an OBSERVATION of a derived boolean, not the setter half of a
|
|
1796
|
+
* controlled value, so the `value`/`defaultValue`/`onValueChange` triad does not apply to it —
|
|
1797
|
+
* the same call `Attachments.onChange` and `ActionsFeedback.onChange` already make here.
|
|
1798
|
+
*/
|
|
1799
|
+
export type AffixProp = {
|
|
1800
|
+
/** What gets pinned. Must not itself be `position: absolute` — antd's note, and it is the same
|
|
1801
|
+
* note here, because the pin works by making this element `position: fixed`. */
|
|
1802
|
+
children?: ChildrenProp;
|
|
1803
|
+
/**
|
|
1804
|
+
* Distance from the scrollport's BLOCK-START edge at which the element pins, in pixels.
|
|
1805
|
+
* Ant Design `offsetTop`, default `0`.
|
|
1806
|
+
*
|
|
1807
|
+
* The name is the logical axis, not `top`, for the reason `check:rtl` exists and the reason
|
|
1808
|
+
* `inset-block-start` replaced `top` in every stylesheet here: a sticky bar in a
|
|
1809
|
+
* `writing-mode: vertical-rl` document pins against the axis it flows on, and "top" is only
|
|
1810
|
+
* the right word for one of the four. `offsetTop` is still FINDABLE — it is declared `never`
|
|
1811
|
+
* below, so arriving from antd's docs is a compile error that names the replacement.
|
|
1812
|
+
*
|
|
1813
|
+
* Pass neither offset and this defaults to `0` (antd's `internalOffsetTop` rule exactly:
|
|
1814
|
+
* the block-start offset defaults to `0` ONLY when the block-end offset is also absent).
|
|
1815
|
+
*/
|
|
1816
|
+
offsetBlockStart?: number;
|
|
1817
|
+
/**
|
|
1818
|
+
* Distance from the scrollport's BLOCK-END edge at which the element pins, in pixels.
|
|
1819
|
+
* Ant Design `offsetBottom`. No default — passing it is what selects block-end pinning.
|
|
1820
|
+
*
|
|
1821
|
+
* Setting both is antd's own precedence: block-start wins, and block-end is only consulted
|
|
1822
|
+
* when the element has not pinned to the start.
|
|
1823
|
+
*/
|
|
1824
|
+
offsetBlockEnd?: number;
|
|
1825
|
+
/**
|
|
1826
|
+
* NOT A PROP — Ant Design's name for `offsetBlockStart`, kept in the type so that arriving from
|
|
1827
|
+
* antd's docs is a compile error that says where to go, rather than a header that never pins
|
|
1828
|
+
* and never complains. Passing it also warns in development.
|
|
1829
|
+
*
|
|
1830
|
+
* @deprecated Ant Design spells this `offsetTop`; in `@godxjp/ui` it is `offsetBlockStart` —
|
|
1831
|
+
* the logical axis, per `check:rtl` and docs/DESIGN-AUTHORITY.md.
|
|
1832
|
+
*/
|
|
1833
|
+
offsetTop?: never;
|
|
1834
|
+
/**
|
|
1835
|
+
* NOT A PROP — Ant Design's name for `offsetBlockEnd`. See `offsetTop`.
|
|
1836
|
+
*
|
|
1837
|
+
* @deprecated Ant Design spells this `offsetBottom`; in `@godxjp/ui` it is `offsetBlockEnd`.
|
|
1838
|
+
*/
|
|
1839
|
+
offsetBottom?: never;
|
|
1840
|
+
/** The scroll box to pin against. Ant Design `target`, default `() => window`. */
|
|
1841
|
+
target?: AffixTargetProp;
|
|
1842
|
+
/**
|
|
1843
|
+
* Fires when the pinned state FLIPS, and only then — never on a scroll frame that did not
|
|
1844
|
+
* change it. Ant Design `onChange`, whose payload is the new state.
|
|
1845
|
+
*
|
|
1846
|
+
* antd types the argument optional (`(affixed?: boolean) => void`) because its own call site can
|
|
1847
|
+
* pass `undefined`; here the transition is derived from a boolean, so the argument is always
|
|
1848
|
+
* present and the type says so. A handler written against antd's signature still compiles.
|
|
1849
|
+
*/
|
|
1850
|
+
onChange?: (affixed: boolean) => void;
|
|
1851
|
+
id?: IdProp;
|
|
1852
|
+
className?: ClassNameProp;
|
|
1853
|
+
};
|