@mindlogic-ai/logician-ui 5.0.0-alpha.12 → 5.0.0-alpha.13
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 +1 -0
- package/dist/components/NavList/NavList.d.ts +34 -0
- package/dist/components/NavList/NavList.d.ts.map +1 -0
- package/dist/components/NavList/NavList.js +113 -0
- package/dist/components/NavList/NavList.js.map +1 -0
- package/dist/components/NavList/NavList.mjs +111 -0
- package/dist/components/NavList/NavList.mjs.map +1 -0
- package/dist/components/NavList/NavList.styles.d.ts +90 -0
- package/dist/components/NavList/NavList.styles.d.ts.map +1 -0
- package/dist/components/NavList/NavList.styles.js +104 -0
- package/dist/components/NavList/NavList.styles.js.map +1 -0
- package/dist/components/NavList/NavList.styles.mjs +97 -0
- package/dist/components/NavList/NavList.styles.mjs.map +1 -0
- package/dist/components/NavList/NavList.translations.json.js +19 -0
- package/dist/components/NavList/NavList.translations.json.js.map +1 -0
- package/dist/components/NavList/NavList.translations.json.mjs +14 -0
- package/dist/components/NavList/NavList.translations.json.mjs.map +1 -0
- package/dist/components/NavList/NavList.types.d.ts +131 -0
- package/dist/components/NavList/NavList.types.d.ts.map +1 -0
- package/dist/components/NavList/NavListContext.d.ts +30 -0
- package/dist/components/NavList/NavListContext.d.ts.map +1 -0
- package/dist/components/NavList/NavListContext.js +16 -0
- package/dist/components/NavList/NavListContext.js.map +1 -0
- package/dist/components/NavList/NavListContext.mjs +13 -0
- package/dist/components/NavList/NavListContext.mjs.map +1 -0
- package/dist/components/NavList/NavListGroup.d.ts +31 -0
- package/dist/components/NavList/NavListGroup.d.ts.map +1 -0
- package/dist/components/NavList/NavListGroup.js +115 -0
- package/dist/components/NavList/NavListGroup.js.map +1 -0
- package/dist/components/NavList/NavListGroup.mjs +113 -0
- package/dist/components/NavList/NavListGroup.mjs.map +1 -0
- package/dist/components/NavList/NavListItem.d.ts +15 -0
- package/dist/components/NavList/NavListItem.d.ts.map +1 -0
- package/dist/components/NavList/NavListItem.js +269 -0
- package/dist/components/NavList/NavListItem.js.map +1 -0
- package/dist/components/NavList/NavListItem.mjs +267 -0
- package/dist/components/NavList/NavListItem.mjs.map +1 -0
- package/dist/components/NavList/NavListSkeleton.d.ts +17 -0
- package/dist/components/NavList/NavListSkeleton.d.ts.map +1 -0
- package/dist/components/NavList/NavListSkeleton.js +33 -0
- package/dist/components/NavList/NavListSkeleton.js.map +1 -0
- package/dist/components/NavList/NavListSkeleton.mjs +31 -0
- package/dist/components/NavList/NavListSkeleton.mjs.map +1 -0
- package/dist/components/NavList/index.d.ts +7 -0
- package/dist/components/NavList/index.d.ts.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -1
- package/dist/index.mjs.map +1 -1
- package/dist/utils/focusRing.d.ts +22 -0
- package/dist/utils/focusRing.d.ts.map +1 -1
- package/dist/utils/focusRing.js +22 -0
- package/dist/utils/focusRing.js.map +1 -1
- package/dist/utils/focusRing.mjs +21 -1
- package/dist/utils/focusRing.mjs.map +1 -1
- package/package.json +2 -1
- package/src/components/Menu/Menu.usage.mdx +8 -0
- package/src/components/NavList/NavList.stories.tsx +895 -0
- package/src/components/NavList/NavList.styles.ts +114 -0
- package/src/components/NavList/NavList.test.tsx +1254 -0
- package/src/components/NavList/NavList.translations.json +9 -0
- package/src/components/NavList/NavList.tsx +160 -0
- package/src/components/NavList/NavList.types.ts +145 -0
- package/src/components/NavList/NavList.usage.mdx +540 -0
- package/src/components/NavList/NavListContext.ts +25 -0
- package/src/components/NavList/NavListGroup.tsx +243 -0
- package/src/components/NavList/NavListItem.tsx +525 -0
- package/src/components/NavList/NavListSkeleton.tsx +57 -0
- package/src/components/NavList/index.ts +14 -0
- package/src/components/Tabs/Tabs.usage.mdx +58 -14
- package/src/components/Tooltip/Tooltip.usage.mdx +8 -0
- package/src/components/a11y.kwcag.test.tsx +66 -0
- package/src/components/claude.md +1 -1
- package/src/index.ts +7 -1
- package/src/utils/focusRing.ts +23 -0
package/README.md
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const NavList: import("react").ForwardRefExoticComponent<Omit<import("@chakra-ui/react").HTMLChakraProps<"ul">, "children"> & {
|
|
2
|
+
children?: import("react").ReactNode;
|
|
3
|
+
orientation?: import("./NavList.types").NavListResponsiveOrientation;
|
|
4
|
+
'aria-label'?: string;
|
|
5
|
+
'aria-labelledby'?: string;
|
|
6
|
+
isCollapsed?: boolean;
|
|
7
|
+
} & import("react").RefAttributes<HTMLUListElement>> & {
|
|
8
|
+
Item: import("react").ForwardRefExoticComponent<Omit<import("@chakra-ui/react").HTMLChakraProps<"a">, "asChild" | "aria-current" | "children" | "onClick"> & {
|
|
9
|
+
children?: import("react").ReactNode;
|
|
10
|
+
href?: string;
|
|
11
|
+
asChild?: boolean;
|
|
12
|
+
onClick?: import("react").MouseEventHandler<HTMLElement>;
|
|
13
|
+
isCurrent?: boolean;
|
|
14
|
+
isDisabled?: boolean;
|
|
15
|
+
leadingVisual?: import("react").ReactNode;
|
|
16
|
+
trailingVisual?: import("react").ReactNode;
|
|
17
|
+
trailingAction?: import("react").ReactNode;
|
|
18
|
+
trailingActionVisibility?: import("./NavList.types").NavListTrailingActionVisibility;
|
|
19
|
+
tooltip?: import("react").ReactNode;
|
|
20
|
+
} & import("react").RefAttributes<HTMLElement>>;
|
|
21
|
+
Group: import("react").ForwardRefExoticComponent<Omit<import("@chakra-ui/react").HTMLChakraProps<"li">, "title" | "children"> & {
|
|
22
|
+
children?: import("react").ReactNode;
|
|
23
|
+
title?: import("react").ReactNode;
|
|
24
|
+
isCollapsible?: boolean;
|
|
25
|
+
isOpen?: boolean;
|
|
26
|
+
defaultOpen?: boolean;
|
|
27
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
28
|
+
} & import("react").RefAttributes<HTMLLIElement>>;
|
|
29
|
+
Skeleton: import("react").ForwardRefExoticComponent<Omit<import("@chakra-ui/react").HTMLChakraProps<"ul">, "children"> & {
|
|
30
|
+
count?: number;
|
|
31
|
+
orientation?: import("./NavList.types").NavListResponsiveOrientation;
|
|
32
|
+
} & import("react").RefAttributes<HTMLUListElement>>;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=NavList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.d.ts","sourceRoot":"","sources":["../../../src/components/NavList/NavList.tsx"],"names":[],"mappings":"AA2JA,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAIlB,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
var React = require('react');
|
|
6
|
+
var react = require('@chakra-ui/react');
|
|
7
|
+
var NavList_styles = require('./NavList.styles.js');
|
|
8
|
+
var NavListContext = require('./NavListContext.js');
|
|
9
|
+
var NavListGroup = require('./NavListGroup.js');
|
|
10
|
+
var NavListItem = require('./NavListItem.js');
|
|
11
|
+
var NavListSkeleton = require('./NavListSkeleton.js');
|
|
12
|
+
|
|
13
|
+
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
|
|
14
|
+
/**
|
|
15
|
+
* Bring the current row into a sideways-scrolling list's visible range, by
|
|
16
|
+
* moving that list's own `scrollLeft` only — never `scrollIntoView`, which
|
|
17
|
+
* also scrolls the page and every scrolling ancestor. A no-op when the list
|
|
18
|
+
* does not scroll sideways (a vertical rail) or the row is already in view.
|
|
19
|
+
*/
|
|
20
|
+
const revealCurrentHorizontally = (list, current) => {
|
|
21
|
+
if (list.scrollWidth <= list.clientWidth)
|
|
22
|
+
return;
|
|
23
|
+
const listBox = list.getBoundingClientRect();
|
|
24
|
+
const rowBox = (current.closest('li') ?? current).getBoundingClientRect();
|
|
25
|
+
// Inside a closed group the row has no box; there is nothing to show.
|
|
26
|
+
if (rowBox.width === 0)
|
|
27
|
+
return;
|
|
28
|
+
if (rowBox.left < listBox.left) {
|
|
29
|
+
list.scrollLeft -= listBox.left - rowBox.left;
|
|
30
|
+
}
|
|
31
|
+
else if (rowBox.right > listBox.right) {
|
|
32
|
+
list.scrollLeft += rowBox.right - listBox.right;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* A vertical list of rows for side navigation and in-page filter rails.
|
|
37
|
+
*
|
|
38
|
+
* Not tabs: there is no tablist, no `aria-selected` and no roving tabindex.
|
|
39
|
+
* Every row is its own link or button in the tab order, and the current one
|
|
40
|
+
* says so with `aria-current`.
|
|
41
|
+
*
|
|
42
|
+
* Named (`aria-label` / `aria-labelledby`), it is a `<nav>` landmark around
|
|
43
|
+
* the list; unnamed, it is just the list. A landmark should have a name once a
|
|
44
|
+
* page has more than one `nav`, and a list inside the app sidebar is already
|
|
45
|
+
* inside one — so the name is what decides whether this is a landmark of its
|
|
46
|
+
* own, rather than a flag the caller has to remember next to it.
|
|
47
|
+
*
|
|
48
|
+
* The ref and every other prop land on the `<ul>` either way — it is the flex
|
|
49
|
+
* and scroll container, so `gap`, `onScroll` and `ref.current.scrollLeft` mean
|
|
50
|
+
* the same thing whether or not the list is named.
|
|
51
|
+
*/
|
|
52
|
+
const NavListRoot = React.forwardRef(({ orientation = 'vertical', isCollapsed = false, children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...rest }, ref) => {
|
|
53
|
+
const isLandmark = ariaLabel != null || ariaLabelledBy != null;
|
|
54
|
+
// A collapsed rail is a column of icons; it has no sideways form.
|
|
55
|
+
const axis = isCollapsed ? 'vertical' : orientation;
|
|
56
|
+
const listRef = React.useRef(null);
|
|
57
|
+
const mergedRef = React.useMemo(() => react.mergeRefs(ref, listRef), [ref]);
|
|
58
|
+
// Reveal the current row when it CHANGES (a row reports it from its own
|
|
59
|
+
// effect, so this works even when only that row re-rendered) and when the
|
|
60
|
+
// list is resized — a strip that just laid down at a breakpoint. Not on
|
|
61
|
+
// every render: a re-render must not snap back a strip the user scrolled.
|
|
62
|
+
const lastRevealed = React.useRef(null);
|
|
63
|
+
const reveal = React.useCallback((force = false) => {
|
|
64
|
+
const list = listRef.current;
|
|
65
|
+
const current = list?.querySelector('[data-current]');
|
|
66
|
+
if (!list || !current)
|
|
67
|
+
return;
|
|
68
|
+
if (!force && current === lastRevealed.current)
|
|
69
|
+
return;
|
|
70
|
+
lastRevealed.current = current;
|
|
71
|
+
revealCurrentHorizontally(list, current);
|
|
72
|
+
}, []);
|
|
73
|
+
React.useEffect(() => {
|
|
74
|
+
const list = listRef.current;
|
|
75
|
+
reveal();
|
|
76
|
+
if (!list || typeof ResizeObserver === 'undefined')
|
|
77
|
+
return;
|
|
78
|
+
const observer = new ResizeObserver(() => reveal(true));
|
|
79
|
+
observer.observe(list);
|
|
80
|
+
return () => observer.disconnect();
|
|
81
|
+
}, [reveal]);
|
|
82
|
+
// Layout never reads this: rows, groups and the list inherit `direction`
|
|
83
|
+
// in CSS, so a right-to-left server render is right on its first paint.
|
|
84
|
+
// Only the rows' TOOLTIPS need it in JS — zag stamps `dir` on their
|
|
85
|
+
// portalled content from Ark's locale, and a popper placement is
|
|
86
|
+
// physical — and a tooltip only opens after hydration, when this is known.
|
|
87
|
+
const [tooltipDir, setTooltipDir] = React.useState('ltr');
|
|
88
|
+
useIsomorphicLayoutEffect(() => {
|
|
89
|
+
const list = listRef.current;
|
|
90
|
+
if (!list)
|
|
91
|
+
return;
|
|
92
|
+
const next = getComputedStyle(list).direction === 'rtl' ? 'rtl' : 'ltr';
|
|
93
|
+
if (next !== tooltipDir)
|
|
94
|
+
setTooltipDir(next);
|
|
95
|
+
});
|
|
96
|
+
const context = React.useMemo(() => ({
|
|
97
|
+
orientation: axis,
|
|
98
|
+
isCollapsed,
|
|
99
|
+
tooltipDir,
|
|
100
|
+
revealCurrent: reveal,
|
|
101
|
+
}), [axis, isCollapsed, tooltipDir, reveal]);
|
|
102
|
+
const list = (jsxRuntime.jsx(react.chakra.ul, { ref: mergedRef, ...NavList_styles.listStyles(axis), overflowX: NavList_styles.byOrientation(axis, 'visible', 'auto'), overflowY: NavList_styles.byOrientation(axis, 'visible', 'hidden'), ...rest, children: children }));
|
|
103
|
+
return (jsxRuntime.jsx(NavListContext.NavListContext.Provider, { value: context, children: isLandmark ? (jsxRuntime.jsx(react.chakra.nav, { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, minW: 0, children: list })) : (list) }));
|
|
104
|
+
});
|
|
105
|
+
NavListRoot.displayName = 'NavList';
|
|
106
|
+
const NavList = Object.assign(NavListRoot, {
|
|
107
|
+
Item: NavListItem.NavListItem,
|
|
108
|
+
Group: NavListGroup.NavListGroup,
|
|
109
|
+
Skeleton: NavListSkeleton.NavListSkeleton,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
exports.NavList = NavList;
|
|
113
|
+
//# sourceMappingURL=NavList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.js","sources":["../../../src/components/NavList/NavList.tsx"],"sourcesContent":[null],"names":["useEffect","useLayoutEffect","forwardRef","useRef","useMemo","mergeRefs","useCallback","useState","_jsx","chakra","listStyles","byOrientation","NavListContext","NavListItem","NavListGroup","NavListSkeleton"],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { forwardRef, useRef, useMemo, useCallback, useEffect, useState, useLayoutEffect } from 'react';
|
|
4
|
+
import { mergeRefs, chakra } from '@chakra-ui/react';
|
|
5
|
+
import { byOrientation, listStyles } from './NavList.styles.mjs';
|
|
6
|
+
import { NavListContext } from './NavListContext.mjs';
|
|
7
|
+
import { NavListGroup } from './NavListGroup.mjs';
|
|
8
|
+
import { NavListItem } from './NavListItem.mjs';
|
|
9
|
+
import { NavListSkeleton } from './NavListSkeleton.mjs';
|
|
10
|
+
|
|
11
|
+
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
|
|
12
|
+
/**
|
|
13
|
+
* Bring the current row into a sideways-scrolling list's visible range, by
|
|
14
|
+
* moving that list's own `scrollLeft` only — never `scrollIntoView`, which
|
|
15
|
+
* also scrolls the page and every scrolling ancestor. A no-op when the list
|
|
16
|
+
* does not scroll sideways (a vertical rail) or the row is already in view.
|
|
17
|
+
*/
|
|
18
|
+
const revealCurrentHorizontally = (list, current) => {
|
|
19
|
+
if (list.scrollWidth <= list.clientWidth)
|
|
20
|
+
return;
|
|
21
|
+
const listBox = list.getBoundingClientRect();
|
|
22
|
+
const rowBox = (current.closest('li') ?? current).getBoundingClientRect();
|
|
23
|
+
// Inside a closed group the row has no box; there is nothing to show.
|
|
24
|
+
if (rowBox.width === 0)
|
|
25
|
+
return;
|
|
26
|
+
if (rowBox.left < listBox.left) {
|
|
27
|
+
list.scrollLeft -= listBox.left - rowBox.left;
|
|
28
|
+
}
|
|
29
|
+
else if (rowBox.right > listBox.right) {
|
|
30
|
+
list.scrollLeft += rowBox.right - listBox.right;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A vertical list of rows for side navigation and in-page filter rails.
|
|
35
|
+
*
|
|
36
|
+
* Not tabs: there is no tablist, no `aria-selected` and no roving tabindex.
|
|
37
|
+
* Every row is its own link or button in the tab order, and the current one
|
|
38
|
+
* says so with `aria-current`.
|
|
39
|
+
*
|
|
40
|
+
* Named (`aria-label` / `aria-labelledby`), it is a `<nav>` landmark around
|
|
41
|
+
* the list; unnamed, it is just the list. A landmark should have a name once a
|
|
42
|
+
* page has more than one `nav`, and a list inside the app sidebar is already
|
|
43
|
+
* inside one — so the name is what decides whether this is a landmark of its
|
|
44
|
+
* own, rather than a flag the caller has to remember next to it.
|
|
45
|
+
*
|
|
46
|
+
* The ref and every other prop land on the `<ul>` either way — it is the flex
|
|
47
|
+
* and scroll container, so `gap`, `onScroll` and `ref.current.scrollLeft` mean
|
|
48
|
+
* the same thing whether or not the list is named.
|
|
49
|
+
*/
|
|
50
|
+
const NavListRoot = forwardRef(({ orientation = 'vertical', isCollapsed = false, children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...rest }, ref) => {
|
|
51
|
+
const isLandmark = ariaLabel != null || ariaLabelledBy != null;
|
|
52
|
+
// A collapsed rail is a column of icons; it has no sideways form.
|
|
53
|
+
const axis = isCollapsed ? 'vertical' : orientation;
|
|
54
|
+
const listRef = useRef(null);
|
|
55
|
+
const mergedRef = useMemo(() => mergeRefs(ref, listRef), [ref]);
|
|
56
|
+
// Reveal the current row when it CHANGES (a row reports it from its own
|
|
57
|
+
// effect, so this works even when only that row re-rendered) and when the
|
|
58
|
+
// list is resized — a strip that just laid down at a breakpoint. Not on
|
|
59
|
+
// every render: a re-render must not snap back a strip the user scrolled.
|
|
60
|
+
const lastRevealed = useRef(null);
|
|
61
|
+
const reveal = useCallback((force = false) => {
|
|
62
|
+
const list = listRef.current;
|
|
63
|
+
const current = list?.querySelector('[data-current]');
|
|
64
|
+
if (!list || !current)
|
|
65
|
+
return;
|
|
66
|
+
if (!force && current === lastRevealed.current)
|
|
67
|
+
return;
|
|
68
|
+
lastRevealed.current = current;
|
|
69
|
+
revealCurrentHorizontally(list, current);
|
|
70
|
+
}, []);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const list = listRef.current;
|
|
73
|
+
reveal();
|
|
74
|
+
if (!list || typeof ResizeObserver === 'undefined')
|
|
75
|
+
return;
|
|
76
|
+
const observer = new ResizeObserver(() => reveal(true));
|
|
77
|
+
observer.observe(list);
|
|
78
|
+
return () => observer.disconnect();
|
|
79
|
+
}, [reveal]);
|
|
80
|
+
// Layout never reads this: rows, groups and the list inherit `direction`
|
|
81
|
+
// in CSS, so a right-to-left server render is right on its first paint.
|
|
82
|
+
// Only the rows' TOOLTIPS need it in JS — zag stamps `dir` on their
|
|
83
|
+
// portalled content from Ark's locale, and a popper placement is
|
|
84
|
+
// physical — and a tooltip only opens after hydration, when this is known.
|
|
85
|
+
const [tooltipDir, setTooltipDir] = useState('ltr');
|
|
86
|
+
useIsomorphicLayoutEffect(() => {
|
|
87
|
+
const list = listRef.current;
|
|
88
|
+
if (!list)
|
|
89
|
+
return;
|
|
90
|
+
const next = getComputedStyle(list).direction === 'rtl' ? 'rtl' : 'ltr';
|
|
91
|
+
if (next !== tooltipDir)
|
|
92
|
+
setTooltipDir(next);
|
|
93
|
+
});
|
|
94
|
+
const context = useMemo(() => ({
|
|
95
|
+
orientation: axis,
|
|
96
|
+
isCollapsed,
|
|
97
|
+
tooltipDir,
|
|
98
|
+
revealCurrent: reveal,
|
|
99
|
+
}), [axis, isCollapsed, tooltipDir, reveal]);
|
|
100
|
+
const list = (jsx(chakra.ul, { ref: mergedRef, ...listStyles(axis), overflowX: byOrientation(axis, 'visible', 'auto'), overflowY: byOrientation(axis, 'visible', 'hidden'), ...rest, children: children }));
|
|
101
|
+
return (jsx(NavListContext.Provider, { value: context, children: isLandmark ? (jsx(chakra.nav, { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, minW: 0, children: list })) : (list) }));
|
|
102
|
+
});
|
|
103
|
+
NavListRoot.displayName = 'NavList';
|
|
104
|
+
const NavList = Object.assign(NavListRoot, {
|
|
105
|
+
Item: NavListItem,
|
|
106
|
+
Group: NavListGroup,
|
|
107
|
+
Skeleton: NavListSkeleton,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export { NavList };
|
|
111
|
+
//# sourceMappingURL=NavList.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.mjs","sources":["../../../src/components/NavList/NavList.tsx"],"sourcesContent":[null],"names":["_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { NavListResponsiveOrientation } from './NavList.types';
|
|
2
|
+
/**
|
|
3
|
+
* The tokens a row paints, exported so the usage page's token table reads what
|
|
4
|
+
* the component renders.
|
|
5
|
+
*
|
|
6
|
+
* **The current row is a PLACE, not a value** — the same rule as `TAB_RAMP`
|
|
7
|
+
* and the app's nav rail (`NavigationLinkButton.utils.tsx` in factchat-nextjs).
|
|
8
|
+
* It is carried by ink, weight and a neutral fill, never by the brand hue: a
|
|
9
|
+
* rail that spends colour on "you are here" is what stops a success or error
|
|
10
|
+
* colour from registering when it appears.
|
|
11
|
+
*
|
|
12
|
+
* `bg.emphasized` rather than `bg.muted` for the fill, because rails sit on the
|
|
13
|
+
* sidebar wash and the fill has to separate from THAT: in light `bg.muted` is
|
|
14
|
+
* only OKLab dE 0.027 from the wash, under the threshold where two flat areas
|
|
15
|
+
* read as different, and `bg.emphasized` is 0.052 (measured in that file).
|
|
16
|
+
* Hover uses the same fill, so the current row does not change under the
|
|
17
|
+
* pointer and a hovered row previews exactly what selecting it looks like.
|
|
18
|
+
*
|
|
19
|
+
* `currentLabel` is `fg.emphasized`, which the theme aliases to `fg.default`
|
|
20
|
+
* today — so on the stock theme the current row is told apart by WEIGHT and
|
|
21
|
+
* FILL, not by a second ink. The role is still named separately so a theme
|
|
22
|
+
* that splits the two (and the app's nav rail, which reads the same pair)
|
|
23
|
+
* moves the current label without touching the rest.
|
|
24
|
+
*
|
|
25
|
+
* **Pressed is one step past hover**, on every row, current ones included —
|
|
26
|
+
* otherwise a press on the row you are already on gives no sign it landed.
|
|
27
|
+
* No `bg.*` role is darker than `bg.emphasized` in light (it is the top of
|
|
28
|
+
* the `layer.1` ladder), so the step is `border.default`: the next neutral in
|
|
29
|
+
* both modes (light `#D8D2CA` after `#E5DFD9`, dark `#48443E` after
|
|
30
|
+
* `#3F3B34`), the same fill the BottomSheet handle uses. Under
|
|
31
|
+
* `prefers-contrast: more` that token turns into a 3:1 stroke grey and the
|
|
32
|
+
* label would drop to 2.8:1, so high contrast takes `border.strong`, which
|
|
33
|
+
* high contrast leaves alone. `NavList.test.tsx` checks every pair.
|
|
34
|
+
*/
|
|
35
|
+
export declare const NAV_LIST_RAMP: {
|
|
36
|
+
readonly label: "fg.default";
|
|
37
|
+
readonly currentLabel: "fg.emphasized";
|
|
38
|
+
readonly currentFill: "bg.emphasized";
|
|
39
|
+
readonly hoverFill: "bg.emphasized";
|
|
40
|
+
readonly pressedFill: "border.default";
|
|
41
|
+
readonly pressedFillMoreContrast: "border.strong";
|
|
42
|
+
readonly trailing: "fg.muted";
|
|
43
|
+
readonly groupTitle: "fg.muted";
|
|
44
|
+
};
|
|
45
|
+
/** The pressed fill, with its high-contrast swap. */
|
|
46
|
+
export declare const pressedFill: {
|
|
47
|
+
readonly bg: "border.default";
|
|
48
|
+
readonly _moreContrast: {
|
|
49
|
+
readonly bg: "border.strong";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Chakra's `_rtl`/`_ltr` and `:dir()` read `dir` ATTRIBUTES, and zag stamps
|
|
54
|
+
* `dir="ltr"` on every part it renders (tooltip triggers — the rows — and the
|
|
55
|
+
* collapsible group) from Ark's locale, before any effect can measure the
|
|
56
|
+
* page. An author `direction` beats the UA rule that maps the attribute, so
|
|
57
|
+
* every stamped element takes the direction it inherits instead: the server
|
|
58
|
+
* render lays an RTL rail out right to left on its first paint.
|
|
59
|
+
*/
|
|
60
|
+
export declare const inheritDirection: {
|
|
61
|
+
readonly direction: "inherit";
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* A locale whose direction is `dir`: the inherited one when it already
|
|
65
|
+
* agrees, so a Korean app keeps formatting in Korean, otherwise a stand-in.
|
|
66
|
+
* Ark has no other way to set the `dir` zag stamps (its hooks omit the prop).
|
|
67
|
+
*/
|
|
68
|
+
export declare const localeFor: (inherited: {
|
|
69
|
+
locale: string;
|
|
70
|
+
dir: "ltr" | "rtl";
|
|
71
|
+
}, dir: "ltr" | "rtl") => string;
|
|
72
|
+
/**
|
|
73
|
+
* Map an orientation (or a per-breakpoint object of them) to a style value per
|
|
74
|
+
* breakpoint, so the axis switch is CSS rather than a `useBreakpointValue`
|
|
75
|
+
* that renders the wrong axis on the server.
|
|
76
|
+
*/
|
|
77
|
+
export declare const byOrientation: <T>(orientation: NavListResponsiveOrientation, vertical: T, horizontal: T) => T | Record<string, T>;
|
|
78
|
+
/** The list box shared by the root list and every group's list. */
|
|
79
|
+
export declare const listStyles: (orientation: NavListResponsiveOrientation) => {
|
|
80
|
+
readonly listStyleType: "none";
|
|
81
|
+
readonly m: 0;
|
|
82
|
+
readonly p: 0;
|
|
83
|
+
readonly display: "flex";
|
|
84
|
+
readonly gap: 0.5;
|
|
85
|
+
readonly minW: 0;
|
|
86
|
+
readonly flexDirection: "row" | "column" | Record<string, "row" | "column">;
|
|
87
|
+
readonly alignItems: "center" | "stretch" | Record<string, "center" | "stretch">;
|
|
88
|
+
readonly flexWrap: "nowrap";
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=NavList.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.styles.d.ts","sourceRoot":"","sources":["../../../src/components/NavList/NavList.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,4BAA4B,EAC7B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,aAAa;;;;;;;;;CAShB,CAAC;AAEX,qDAAqD;AACrD,eAAO,MAAM,WAAW;;;;;CAGd,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;CAAoC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,SAAS,GACpB,WAAW;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,KAAK,GAAG,KAAK,CAAA;CAAE,EACjD,KAAK,KAAK,GAAG,KAAK,WAEuD,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,EAC7B,aAAa,4BAA4B,EACzC,UAAU,CAAC,EACX,YAAY,CAAC,KACZ,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAYtB,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,UAAU,GAAI,aAAa,4BAA4B;;;;;;;;;;CAavD,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The tokens a row paints, exported so the usage page's token table reads what
|
|
6
|
+
* the component renders.
|
|
7
|
+
*
|
|
8
|
+
* **The current row is a PLACE, not a value** — the same rule as `TAB_RAMP`
|
|
9
|
+
* and the app's nav rail (`NavigationLinkButton.utils.tsx` in factchat-nextjs).
|
|
10
|
+
* It is carried by ink, weight and a neutral fill, never by the brand hue: a
|
|
11
|
+
* rail that spends colour on "you are here" is what stops a success or error
|
|
12
|
+
* colour from registering when it appears.
|
|
13
|
+
*
|
|
14
|
+
* `bg.emphasized` rather than `bg.muted` for the fill, because rails sit on the
|
|
15
|
+
* sidebar wash and the fill has to separate from THAT: in light `bg.muted` is
|
|
16
|
+
* only OKLab dE 0.027 from the wash, under the threshold where two flat areas
|
|
17
|
+
* read as different, and `bg.emphasized` is 0.052 (measured in that file).
|
|
18
|
+
* Hover uses the same fill, so the current row does not change under the
|
|
19
|
+
* pointer and a hovered row previews exactly what selecting it looks like.
|
|
20
|
+
*
|
|
21
|
+
* `currentLabel` is `fg.emphasized`, which the theme aliases to `fg.default`
|
|
22
|
+
* today — so on the stock theme the current row is told apart by WEIGHT and
|
|
23
|
+
* FILL, not by a second ink. The role is still named separately so a theme
|
|
24
|
+
* that splits the two (and the app's nav rail, which reads the same pair)
|
|
25
|
+
* moves the current label without touching the rest.
|
|
26
|
+
*
|
|
27
|
+
* **Pressed is one step past hover**, on every row, current ones included —
|
|
28
|
+
* otherwise a press on the row you are already on gives no sign it landed.
|
|
29
|
+
* No `bg.*` role is darker than `bg.emphasized` in light (it is the top of
|
|
30
|
+
* the `layer.1` ladder), so the step is `border.default`: the next neutral in
|
|
31
|
+
* both modes (light `#D8D2CA` after `#E5DFD9`, dark `#48443E` after
|
|
32
|
+
* `#3F3B34`), the same fill the BottomSheet handle uses. Under
|
|
33
|
+
* `prefers-contrast: more` that token turns into a 3:1 stroke grey and the
|
|
34
|
+
* label would drop to 2.8:1, so high contrast takes `border.strong`, which
|
|
35
|
+
* high contrast leaves alone. `NavList.test.tsx` checks every pair.
|
|
36
|
+
*/
|
|
37
|
+
const NAV_LIST_RAMP = {
|
|
38
|
+
label: 'fg.default',
|
|
39
|
+
currentLabel: 'fg.emphasized',
|
|
40
|
+
currentFill: 'bg.emphasized',
|
|
41
|
+
hoverFill: 'bg.emphasized',
|
|
42
|
+
pressedFill: 'border.default',
|
|
43
|
+
pressedFillMoreContrast: 'border.strong',
|
|
44
|
+
trailing: 'fg.muted',
|
|
45
|
+
groupTitle: 'fg.muted',
|
|
46
|
+
};
|
|
47
|
+
/** The pressed fill, with its high-contrast swap. */
|
|
48
|
+
const pressedFill = {
|
|
49
|
+
bg: NAV_LIST_RAMP.pressedFill,
|
|
50
|
+
_moreContrast: { bg: NAV_LIST_RAMP.pressedFillMoreContrast },
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Chakra's `_rtl`/`_ltr` and `:dir()` read `dir` ATTRIBUTES, and zag stamps
|
|
54
|
+
* `dir="ltr"` on every part it renders (tooltip triggers — the rows — and the
|
|
55
|
+
* collapsible group) from Ark's locale, before any effect can measure the
|
|
56
|
+
* page. An author `direction` beats the UA rule that maps the attribute, so
|
|
57
|
+
* every stamped element takes the direction it inherits instead: the server
|
|
58
|
+
* render lays an RTL rail out right to left on its first paint.
|
|
59
|
+
*/
|
|
60
|
+
const inheritDirection = { direction: 'inherit' };
|
|
61
|
+
/**
|
|
62
|
+
* A locale whose direction is `dir`: the inherited one when it already
|
|
63
|
+
* agrees, so a Korean app keeps formatting in Korean, otherwise a stand-in.
|
|
64
|
+
* Ark has no other way to set the `dir` zag stamps (its hooks omit the prop).
|
|
65
|
+
*/
|
|
66
|
+
const localeFor = (inherited, dir) => inherited.dir === dir ? inherited.locale : dir === 'rtl' ? 'ar' : 'en-US';
|
|
67
|
+
/**
|
|
68
|
+
* Map an orientation (or a per-breakpoint object of them) to a style value per
|
|
69
|
+
* breakpoint, so the axis switch is CSS rather than a `useBreakpointValue`
|
|
70
|
+
* that renders the wrong axis on the server.
|
|
71
|
+
*/
|
|
72
|
+
const byOrientation = (orientation, vertical, horizontal) => {
|
|
73
|
+
const pick = (o) => o === 'horizontal' ? horizontal : vertical;
|
|
74
|
+
if (typeof orientation === 'string')
|
|
75
|
+
return pick(orientation);
|
|
76
|
+
// A breakpoint object with no `base` still starts vertical — the default —
|
|
77
|
+
// instead of leaving the smallest screens with no axis at all.
|
|
78
|
+
return Object.fromEntries(Object.entries({ base: 'vertical', ...orientation }).map(([bp, o]) => [
|
|
79
|
+
bp,
|
|
80
|
+
pick(o),
|
|
81
|
+
]));
|
|
82
|
+
};
|
|
83
|
+
/** The list box shared by the root list and every group's list. */
|
|
84
|
+
const listStyles = (orientation) => ({
|
|
85
|
+
listStyleType: 'none',
|
|
86
|
+
m: 0,
|
|
87
|
+
p: 0,
|
|
88
|
+
display: 'flex',
|
|
89
|
+
gap: 0.5,
|
|
90
|
+
minW: 0,
|
|
91
|
+
flexDirection: byOrientation(orientation, 'column', 'row'),
|
|
92
|
+
alignItems: byOrientation(orientation, 'stretch', 'center'),
|
|
93
|
+
// A row never wraps: a strip that grows to three lines as items are added
|
|
94
|
+
// eats the content it navigates. The root scrolls sideways instead.
|
|
95
|
+
flexWrap: 'nowrap',
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
exports.NAV_LIST_RAMP = NAV_LIST_RAMP;
|
|
99
|
+
exports.byOrientation = byOrientation;
|
|
100
|
+
exports.inheritDirection = inheritDirection;
|
|
101
|
+
exports.listStyles = listStyles;
|
|
102
|
+
exports.localeFor = localeFor;
|
|
103
|
+
exports.pressedFill = pressedFill;
|
|
104
|
+
//# sourceMappingURL=NavList.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.styles.js","sources":["../../../src/components/NavList/NavList.styles.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI,MAAM,aAAa,GAAG;AAC3B,IAAA,KAAK,EAAE,YAAY;AACnB,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,WAAW,EAAE,eAAe;AAC5B,IAAA,SAAS,EAAE,eAAe;AAC1B,IAAA,WAAW,EAAE,gBAAgB;AAC7B,IAAA,uBAAuB,EAAE,eAAe;AACxC,IAAA,QAAQ,EAAE,UAAU;AACpB,IAAA,UAAU,EAAE,UAAU;;AAGxB;AACO,MAAM,WAAW,GAAG;IACzB,EAAE,EAAE,aAAa,CAAC,WAAW;AAC7B,IAAA,aAAa,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,uBAAuB,EAAE;;AAG9D;;;;;;;AAOG;MACU,gBAAgB,GAAG,EAAE,SAAS,EAAE,SAAS;AAEtD;;;;AAIG;AACI,MAAM,SAAS,GAAG,CACvB,SAAiD,EACjD,GAAkB,KAElB,SAAS,CAAC,GAAG,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,GAAG,GAAG,KAAK,KAAK,GAAG,IAAI,GAAG;AAEpE;;;;AAIG;AACI,MAAM,aAAa,GAAG,CAC3B,WAAyC,EACzC,QAAW,EACX,UAAa,KACY;AACzB,IAAA,MAAM,IAAI,GAAG,CAAC,CAAqB,KACjC,CAAC,KAAK,YAAY,GAAG,UAAU,GAAG,QAAQ;IAC5C,IAAI,OAAO,WAAW,KAAK,QAAQ;AAAE,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC;;;AAG7D,IAAA,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK;QACpE,EAAE;QACF,IAAI,CAAC,CAAuB,CAAC;AAC9B,KAAA,CAAC,CACH;AACH;AAEA;MACa,UAAU,GAAG,CAAC,WAAyC,MACjE;AACC,IAAA,aAAa,EAAE,MAAM;AACrB,IAAA,CAAC,EAAE,CAAC;AACJ,IAAA,CAAC,EAAE,CAAC;AACJ,IAAA,OAAO,EAAE,MAAM;AACf,IAAA,GAAG,EAAE,GAAG;AACR,IAAA,IAAI,EAAE,CAAC;IACP,aAAa,EAAE,aAAa,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC;IAC1D,UAAU,EAAE,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC;;;AAG3D,IAAA,QAAQ,EAAE,QAAQ;AACnB,CAAA;;;;;;;;;"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* The tokens a row paints, exported so the usage page's token table reads what
|
|
4
|
+
* the component renders.
|
|
5
|
+
*
|
|
6
|
+
* **The current row is a PLACE, not a value** — the same rule as `TAB_RAMP`
|
|
7
|
+
* and the app's nav rail (`NavigationLinkButton.utils.tsx` in factchat-nextjs).
|
|
8
|
+
* It is carried by ink, weight and a neutral fill, never by the brand hue: a
|
|
9
|
+
* rail that spends colour on "you are here" is what stops a success or error
|
|
10
|
+
* colour from registering when it appears.
|
|
11
|
+
*
|
|
12
|
+
* `bg.emphasized` rather than `bg.muted` for the fill, because rails sit on the
|
|
13
|
+
* sidebar wash and the fill has to separate from THAT: in light `bg.muted` is
|
|
14
|
+
* only OKLab dE 0.027 from the wash, under the threshold where two flat areas
|
|
15
|
+
* read as different, and `bg.emphasized` is 0.052 (measured in that file).
|
|
16
|
+
* Hover uses the same fill, so the current row does not change under the
|
|
17
|
+
* pointer and a hovered row previews exactly what selecting it looks like.
|
|
18
|
+
*
|
|
19
|
+
* `currentLabel` is `fg.emphasized`, which the theme aliases to `fg.default`
|
|
20
|
+
* today — so on the stock theme the current row is told apart by WEIGHT and
|
|
21
|
+
* FILL, not by a second ink. The role is still named separately so a theme
|
|
22
|
+
* that splits the two (and the app's nav rail, which reads the same pair)
|
|
23
|
+
* moves the current label without touching the rest.
|
|
24
|
+
*
|
|
25
|
+
* **Pressed is one step past hover**, on every row, current ones included —
|
|
26
|
+
* otherwise a press on the row you are already on gives no sign it landed.
|
|
27
|
+
* No `bg.*` role is darker than `bg.emphasized` in light (it is the top of
|
|
28
|
+
* the `layer.1` ladder), so the step is `border.default`: the next neutral in
|
|
29
|
+
* both modes (light `#D8D2CA` after `#E5DFD9`, dark `#48443E` after
|
|
30
|
+
* `#3F3B34`), the same fill the BottomSheet handle uses. Under
|
|
31
|
+
* `prefers-contrast: more` that token turns into a 3:1 stroke grey and the
|
|
32
|
+
* label would drop to 2.8:1, so high contrast takes `border.strong`, which
|
|
33
|
+
* high contrast leaves alone. `NavList.test.tsx` checks every pair.
|
|
34
|
+
*/
|
|
35
|
+
const NAV_LIST_RAMP = {
|
|
36
|
+
label: 'fg.default',
|
|
37
|
+
currentLabel: 'fg.emphasized',
|
|
38
|
+
currentFill: 'bg.emphasized',
|
|
39
|
+
hoverFill: 'bg.emphasized',
|
|
40
|
+
pressedFill: 'border.default',
|
|
41
|
+
pressedFillMoreContrast: 'border.strong',
|
|
42
|
+
trailing: 'fg.muted',
|
|
43
|
+
groupTitle: 'fg.muted',
|
|
44
|
+
};
|
|
45
|
+
/** The pressed fill, with its high-contrast swap. */
|
|
46
|
+
const pressedFill = {
|
|
47
|
+
bg: NAV_LIST_RAMP.pressedFill,
|
|
48
|
+
_moreContrast: { bg: NAV_LIST_RAMP.pressedFillMoreContrast },
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Chakra's `_rtl`/`_ltr` and `:dir()` read `dir` ATTRIBUTES, and zag stamps
|
|
52
|
+
* `dir="ltr"` on every part it renders (tooltip triggers — the rows — and the
|
|
53
|
+
* collapsible group) from Ark's locale, before any effect can measure the
|
|
54
|
+
* page. An author `direction` beats the UA rule that maps the attribute, so
|
|
55
|
+
* every stamped element takes the direction it inherits instead: the server
|
|
56
|
+
* render lays an RTL rail out right to left on its first paint.
|
|
57
|
+
*/
|
|
58
|
+
const inheritDirection = { direction: 'inherit' };
|
|
59
|
+
/**
|
|
60
|
+
* A locale whose direction is `dir`: the inherited one when it already
|
|
61
|
+
* agrees, so a Korean app keeps formatting in Korean, otherwise a stand-in.
|
|
62
|
+
* Ark has no other way to set the `dir` zag stamps (its hooks omit the prop).
|
|
63
|
+
*/
|
|
64
|
+
const localeFor = (inherited, dir) => inherited.dir === dir ? inherited.locale : dir === 'rtl' ? 'ar' : 'en-US';
|
|
65
|
+
/**
|
|
66
|
+
* Map an orientation (or a per-breakpoint object of them) to a style value per
|
|
67
|
+
* breakpoint, so the axis switch is CSS rather than a `useBreakpointValue`
|
|
68
|
+
* that renders the wrong axis on the server.
|
|
69
|
+
*/
|
|
70
|
+
const byOrientation = (orientation, vertical, horizontal) => {
|
|
71
|
+
const pick = (o) => o === 'horizontal' ? horizontal : vertical;
|
|
72
|
+
if (typeof orientation === 'string')
|
|
73
|
+
return pick(orientation);
|
|
74
|
+
// A breakpoint object with no `base` still starts vertical — the default —
|
|
75
|
+
// instead of leaving the smallest screens with no axis at all.
|
|
76
|
+
return Object.fromEntries(Object.entries({ base: 'vertical', ...orientation }).map(([bp, o]) => [
|
|
77
|
+
bp,
|
|
78
|
+
pick(o),
|
|
79
|
+
]));
|
|
80
|
+
};
|
|
81
|
+
/** The list box shared by the root list and every group's list. */
|
|
82
|
+
const listStyles = (orientation) => ({
|
|
83
|
+
listStyleType: 'none',
|
|
84
|
+
m: 0,
|
|
85
|
+
p: 0,
|
|
86
|
+
display: 'flex',
|
|
87
|
+
gap: 0.5,
|
|
88
|
+
minW: 0,
|
|
89
|
+
flexDirection: byOrientation(orientation, 'column', 'row'),
|
|
90
|
+
alignItems: byOrientation(orientation, 'stretch', 'center'),
|
|
91
|
+
// A row never wraps: a strip that grows to three lines as items are added
|
|
92
|
+
// eats the content it navigates. The root scrolls sideways instead.
|
|
93
|
+
flexWrap: 'nowrap',
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export { NAV_LIST_RAMP, byOrientation, inheritDirection, listStyles, localeFor, pressedFill };
|
|
97
|
+
//# sourceMappingURL=NavList.styles.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.styles.mjs","sources":["../../../src/components/NavList/NavList.styles.ts"],"sourcesContent":[null],"names":[],"mappings":";AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI,MAAM,aAAa,GAAG;AAC3B,IAAA,KAAK,EAAE,YAAY;AACnB,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,WAAW,EAAE,eAAe;AAC5B,IAAA,SAAS,EAAE,eAAe;AAC1B,IAAA,WAAW,EAAE,gBAAgB;AAC7B,IAAA,uBAAuB,EAAE,eAAe;AACxC,IAAA,QAAQ,EAAE,UAAU;AACpB,IAAA,UAAU,EAAE,UAAU;;AAGxB;AACO,MAAM,WAAW,GAAG;IACzB,EAAE,EAAE,aAAa,CAAC,WAAW;AAC7B,IAAA,aAAa,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,uBAAuB,EAAE;;AAG9D;;;;;;;AAOG;MACU,gBAAgB,GAAG,EAAE,SAAS,EAAE,SAAS;AAEtD;;;;AAIG;AACI,MAAM,SAAS,GAAG,CACvB,SAAiD,EACjD,GAAkB,KAElB,SAAS,CAAC,GAAG,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,GAAG,GAAG,KAAK,KAAK,GAAG,IAAI,GAAG;AAEpE;;;;AAIG;AACI,MAAM,aAAa,GAAG,CAC3B,WAAyC,EACzC,QAAW,EACX,UAAa,KACY;AACzB,IAAA,MAAM,IAAI,GAAG,CAAC,CAAqB,KACjC,CAAC,KAAK,YAAY,GAAG,UAAU,GAAG,QAAQ;IAC5C,IAAI,OAAO,WAAW,KAAK,QAAQ;AAAE,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC;;;AAG7D,IAAA,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK;QACpE,EAAE;QACF,IAAI,CAAC,CAAuB,CAAC;AAC9B,KAAA,CAAC,CACH;AACH;AAEA;MACa,UAAU,GAAG,CAAC,WAAyC,MACjE;AACC,IAAA,aAAa,EAAE,MAAM;AACrB,IAAA,CAAC,EAAE,CAAC;AACJ,IAAA,CAAC,EAAE,CAAC;AACJ,IAAA,OAAO,EAAE,MAAM;AACf,IAAA,GAAG,EAAE,GAAG;AACR,IAAA,IAAI,EAAE,CAAC;IACP,aAAa,EAAE,aAAa,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC;IAC1D,UAAU,EAAE,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC;;;AAG3D,IAAA,QAAQ,EAAE,QAAQ;AACnB,CAAA;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var nav_list_opens_new_window = {
|
|
7
|
+
ko: "새 창 열림",
|
|
8
|
+
en: "opens in a new window",
|
|
9
|
+
zh: "在新窗口中打开",
|
|
10
|
+
ja: "新しいウィンドウで開く",
|
|
11
|
+
es: "se abre en una ventana nueva"
|
|
12
|
+
};
|
|
13
|
+
var NavListTranslations = {
|
|
14
|
+
nav_list_opens_new_window: nav_list_opens_new_window
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
exports.default = NavListTranslations;
|
|
18
|
+
exports.nav_list_opens_new_window = nav_list_opens_new_window;
|
|
19
|
+
//# sourceMappingURL=NavList.translations.json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.translations.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var nav_list_opens_new_window = {
|
|
3
|
+
ko: "새 창 열림",
|
|
4
|
+
en: "opens in a new window",
|
|
5
|
+
zh: "在新窗口中打开",
|
|
6
|
+
ja: "新しいウィンドウで開く",
|
|
7
|
+
es: "se abre en una ventana nueva"
|
|
8
|
+
};
|
|
9
|
+
var NavListTranslations = {
|
|
10
|
+
nav_list_opens_new_window: nav_list_opens_new_window
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { NavListTranslations as default, nav_list_opens_new_window };
|
|
14
|
+
//# sourceMappingURL=NavList.translations.json.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavList.translations.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|