@primer/react 38.27.0-rc.179829ffc → 38.27.0-rc.1c9d7ead9
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/CHANGELOG.md +10 -0
- package/dist/KeybindingHint/KeybindingHint.d.ts +6 -1
- package/dist/KeybindingHint/KeybindingHint.d.ts.map +1 -1
- package/dist/KeybindingHint/KeybindingHint.js +6 -2
- package/dist/KeybindingHint/components/Chord.d.ts +2 -1
- package/dist/KeybindingHint/components/Chord.d.ts.map +1 -1
- package/dist/KeybindingHint/components/Chord.js +1 -1
- package/dist/KeybindingHint/components/Key.js +10 -10
- package/dist/KeybindingHint/components/Sequence.d.ts +2 -1
- package/dist/KeybindingHint/components/Sequence.d.ts.map +1 -1
- package/dist/KeybindingHint/components/Sequence.js +2 -2
- package/dist/KeybindingHint/key-names.d.ts +4 -3
- package/dist/KeybindingHint/key-names.d.ts.map +1 -1
- package/dist/KeybindingHint/key-names.js +15 -14
- package/dist/KeybindingHint/platform.d.ts +22 -0
- package/dist/KeybindingHint/platform.d.ts.map +1 -0
- package/dist/KeybindingHint/platform.js +61 -0
- package/dist/TooltipV2/Tooltip.d.ts.map +1 -1
- package/dist/TooltipV2/Tooltip.js +3 -3
- package/dist/TreeView/TreeView-1bf45a33.css +2 -0
- package/dist/TreeView/TreeView-1bf45a33.css.map +1 -0
- package/dist/TreeView/TreeView.d.ts.map +1 -1
- package/dist/TreeView/TreeView.js +25 -12
- package/dist/TreeView/TreeView.module.css.js +2 -2
- package/generated/components.json +4 -0
- package/package.json +1 -1
- package/dist/TreeView/TreeView-0fe09f34.css +0 -2
- package/dist/TreeView/TreeView-0fe09f34.css.map +0 -1
- package/dist/hooks/useIsMacOS.js +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -10,8 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### Patch Changes
|
|
12
12
|
|
|
13
|
+
- [#7908](https://github.com/primer/react/pull/7908) [`e9a2254`](https://github.com/primer/react/commit/e9a225421df61e7fa62da1b2796972122d266d36) Thanks [@jonrohan](https://github.com/jonrohan)! - `KeybindingHint`: display the `Meta` key correctly on platforms other than macOS and Windows. The `Meta`, `Alt`, and `Mod` keys are now resolved based on the detected platform: Apple platforms (macOS and iOS) show `⌘`/`⌥`, Windows shows `Win`, and all other platforms show `Meta`/`Alt`.
|
|
14
|
+
|
|
13
15
|
- [#7894](https://github.com/primer/react/pull/7894) [`af4541d`](https://github.com/primer/react/commit/af4541d991c6e583dbf510bd0a0699f244ea00b2) Thanks [@mattcosta7](https://github.com/mattcosta7)! - ActionList: Replace `:has(...)` selectors on `ActionList.Item`, `InactiveButtonWrap`, and `TrailingActionButton` with JS-derived data attributes (`data-has-trailing-action`, `data-trailing-action-loading`, `data-position`, `data-has-label`). Reduces style-recalculation cost on lists that render many items. No visual or behavioral changes.
|
|
14
16
|
|
|
17
|
+
- [#7899](https://github.com/primer/react/pull/7899) [`9659ce7`](https://github.com/primer/react/commit/9659ce767760d85c033e43e7e8ecdfdfb452dcb1) Thanks [@mattcosta7](https://github.com/mattcosta7)! - `TreeView`: make rows safer to use with `contain: paint` / `content-visibility: auto` and reduce style-recalc cost on hover/focus in large trees. No visual or layout changes; all changes are either invisible at the default rendering or behind an opt-in CSS containment property the consumer sets.
|
|
18
|
+
|
|
19
|
+
- The current-item indicator (positioned at `left: -8px` of the row container) was being clipped when a consumer applied `contain: paint` to the `<li>` or when the documented `containIntrinsicSize` prop on `TreeView.Item` triggered `content-visibility: auto` on the row container — including for `current` items. Both `.TreeViewItem` and `.TreeViewItemContainer` now declare `overflow-clip-margin: var(--base-size-8)`, which extends the paint-clip edge by 8px on the side the indicator paints. The property is a no-op when no paint containment is active, so default rendering is byte-identical.
|
|
20
|
+
- Skeleton-row hover suppression no longer relies on `:has(.TreeViewItemSkeleton)`, which forced subtree invalidation on every row. `LoadingItem` now communicates with the placeholder `Item` via a module-private context that emits a positive `data-loading` attribute on the `<li>`, and the CSS selector targets that directly. No new public prop.
|
|
21
|
+
- Nesting indicator lines no longer use a root-scope `:hover`/`:focus-within` descendant selector. Color is driven by an inherited `--tree-line-color` custom property set on the root `<ul>`, so a hover or focus change inside the tree updates one property on one element instead of re-matching `.TreeViewItemLevelLine` selectors against every level line in the tree.
|
|
22
|
+
- Fixed a unitless `outline-offset: -2` in the forced-colors focus-ring fallback that browsers were silently dropping (so forced-colors users now actually get a focus indicator on tree items).
|
|
23
|
+
- `.TreeViewItemContainer`'s `grid-template-columns` now declares the `trailingAction` column explicitly (`auto`) so it matches the 5-area `grid-template-areas` declaration (previously the trailing column was implicit `auto`).
|
|
24
|
+
|
|
15
25
|
## 38.26.0
|
|
16
26
|
|
|
17
27
|
### Minor Changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { KeybindingHintProps } from './props';
|
|
2
|
+
import type { Platform } from './platform';
|
|
2
3
|
/** Indicates the presence of an available keybinding. */
|
|
3
4
|
export declare const KeybindingHint: import("react").MemoExoticComponent<({ className, ...props }: KeybindingHintProps) => import("react").JSX.Element>;
|
|
4
5
|
/**
|
|
@@ -8,6 +9,10 @@ export declare const KeybindingHint: import("react").MemoExoticComponent<({ clas
|
|
|
8
9
|
*
|
|
9
10
|
* NOTE that this string should _only_ be used when building `aria-label` or `aria-description` props (never rendered
|
|
10
11
|
* visibly) and should nearly always also be paired with a visible hint for sighted users.
|
|
12
|
+
*
|
|
13
|
+
* The `platform` argument controls how platform-specific keys (such as `Meta`, `Alt`, and `Mod`) are named. For
|
|
14
|
+
* backwards compatibility, a `boolean` may be passed instead, where `true` is treated as `'apple'` and `false` as
|
|
15
|
+
* `'other'`.
|
|
11
16
|
*/
|
|
12
|
-
export declare const getAccessibleKeybindingHintString: (sequence: string,
|
|
17
|
+
export declare const getAccessibleKeybindingHintString: (sequence: string, platform: Platform | boolean) => string;
|
|
13
18
|
//# sourceMappingURL=KeybindingHint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeybindingHint.d.ts","sourceRoot":"","sources":["../../src/KeybindingHint/KeybindingHint.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"KeybindingHint.d.ts","sourceRoot":"","sources":["../../src/KeybindingHint/KeybindingHint.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,SAAS,CAAA;AAEhD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAA;AAmBxC,yDAAyD;AAEzD,eAAO,MAAM,cAAc,gEAAgC,mBAAmB,iCAI5E,CAAA;AAGF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,GAAI,UAAU,MAAM,EAAE,UAAU,QAAQ,GAAG,OAAO,WACe,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c } from 'react-compiler-runtime';
|
|
2
2
|
import { memo } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { Sequence, accessibleSequenceString } from './components/Sequence.js';
|
|
4
4
|
import classes from './KeybindingHint.module.css.js';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
6
|
import { jsx } from 'react/jsx-runtime';
|
|
@@ -89,7 +89,11 @@ KeybindingHint.displayName = 'KeybindingHint';
|
|
|
89
89
|
*
|
|
90
90
|
* NOTE that this string should _only_ be used when building `aria-label` or `aria-description` props (never rendered
|
|
91
91
|
* visibly) and should nearly always also be paired with a visible hint for sighted users.
|
|
92
|
+
*
|
|
93
|
+
* The `platform` argument controls how platform-specific keys (such as `Meta`, `Alt`, and `Mod`) are named. For
|
|
94
|
+
* backwards compatibility, a `boolean` may be passed instead, where `true` is treated as `'apple'` and `false` as
|
|
95
|
+
* `'other'`.
|
|
92
96
|
*/
|
|
93
|
-
const getAccessibleKeybindingHintString = accessibleSequenceString;
|
|
97
|
+
const getAccessibleKeybindingHintString = (sequence, platform) => accessibleSequenceString(sequence, typeof platform === 'boolean' ? platform ? 'apple' : 'other' : platform);
|
|
94
98
|
|
|
95
99
|
export { KeybindingHint, getAccessibleKeybindingHintString };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { KeybindingHintProps } from '../props';
|
|
2
|
+
import type { Platform } from '../platform';
|
|
2
3
|
export declare const Chord: ({ keys, format, variant, size }: KeybindingHintProps) => import("react").JSX.Element;
|
|
3
4
|
/** Plain string version of `Chord` for use in `aria` string attributes. */
|
|
4
|
-
export declare const accessibleChordString: (chord: string,
|
|
5
|
+
export declare const accessibleChordString: (chord: string, platform: Platform) => string;
|
|
5
6
|
//# sourceMappingURL=Chord.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chord.d.ts","sourceRoot":"","sources":["../../../src/KeybindingHint/components/Chord.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"Chord.d.ts","sourceRoot":"","sources":["../../../src/KeybindingHint/components/Chord.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAA;AAGjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AA6BzC,eAAO,MAAM,KAAK,GAAI,iCAAmE,mBAAmB,gCAsB3G,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,EAAE,UAAU,QAAQ,WAGzD,CAAA"}
|
|
@@ -96,6 +96,6 @@ const Chord = t0 => {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
/** Plain string version of `Chord` for use in `aria` string attributes. */
|
|
99
|
-
const accessibleChordString = (chord,
|
|
99
|
+
const accessibleChordString = (chord, platform) => splitChord(chord).map(key => accessibleKeyName(key, platform)).join(' ');
|
|
100
100
|
|
|
101
101
|
export { Chord, accessibleChordString };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c } from 'react-compiler-runtime';
|
|
2
2
|
import VisuallyHidden from '../../_VisuallyHidden.js';
|
|
3
3
|
import { accessibleKeyName, condensedKeyName, fullKeyName } from '../key-names.js';
|
|
4
|
-
import {
|
|
4
|
+
import { usePlatform } from '../platform.js';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/** Renders a single key with accessible alternative text. */
|
|
@@ -11,12 +11,12 @@ const Key = t0 => {
|
|
|
11
11
|
name,
|
|
12
12
|
format
|
|
13
13
|
} = t0;
|
|
14
|
-
const
|
|
14
|
+
const platform = usePlatform();
|
|
15
15
|
let t1;
|
|
16
|
-
if ($[0] !==
|
|
17
|
-
t1 = accessibleKeyName(name,
|
|
18
|
-
$[0] =
|
|
19
|
-
$[1] =
|
|
16
|
+
if ($[0] !== name || $[1] !== platform) {
|
|
17
|
+
t1 = accessibleKeyName(name, platform);
|
|
18
|
+
$[0] = name;
|
|
19
|
+
$[1] = platform;
|
|
20
20
|
$[2] = t1;
|
|
21
21
|
} else {
|
|
22
22
|
t1 = $[2];
|
|
@@ -32,11 +32,11 @@ const Key = t0 => {
|
|
|
32
32
|
t2 = $[4];
|
|
33
33
|
}
|
|
34
34
|
let t3;
|
|
35
|
-
if ($[5] !== format || $[6] !==
|
|
36
|
-
t3 = format === "condensed" ? condensedKeyName(name,
|
|
35
|
+
if ($[5] !== format || $[6] !== name || $[7] !== platform) {
|
|
36
|
+
t3 = format === "condensed" ? condensedKeyName(name, platform) : fullKeyName(name, platform);
|
|
37
37
|
$[5] = format;
|
|
38
|
-
$[6] =
|
|
39
|
-
$[7] =
|
|
38
|
+
$[6] = name;
|
|
39
|
+
$[7] = platform;
|
|
40
40
|
$[8] = t3;
|
|
41
41
|
} else {
|
|
42
42
|
t3 = $[8];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { KeybindingHintProps } from '../props';
|
|
2
|
+
import type { Platform } from '../platform';
|
|
2
3
|
export declare const Sequence: ({ keys, ...chordProps }: KeybindingHintProps) => import("react").JSX.Element[];
|
|
3
4
|
/** Plain string version of `Sequence` for use in `aria` string attributes. */
|
|
4
|
-
export declare const accessibleSequenceString: (sequence: string,
|
|
5
|
+
export declare const accessibleSequenceString: (sequence: string, platform: Platform) => string;
|
|
5
6
|
//# sourceMappingURL=Sequence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sequence.d.ts","sourceRoot":"","sources":["../../../src/KeybindingHint/components/Sequence.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"Sequence.d.ts","sourceRoot":"","sources":["../../../src/KeybindingHint/components/Sequence.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAA;AAGjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AAIzC,eAAO,MAAM,QAAQ,GAAI,yBAAuB,mBAAmB,kCAa/D,CAAA;AAEJ,8EAA8E;AAC9E,eAAO,MAAM,wBAAwB,GAAI,UAAU,MAAM,EAAE,UAAU,QAAQ,WAG1D,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment } from 'react';
|
|
2
2
|
import VisuallyHidden from '../../_VisuallyHidden.js';
|
|
3
|
-
import {
|
|
3
|
+
import { Chord, accessibleChordString } from './Chord.js';
|
|
4
4
|
import { jsxs, Fragment as Fragment$1, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
const splitSequence = sequence => sequence.split(' ');
|
|
@@ -21,6 +21,6 @@ const Sequence = ({
|
|
|
21
21
|
}, i));
|
|
22
22
|
|
|
23
23
|
/** Plain string version of `Sequence` for use in `aria` string attributes. */
|
|
24
|
-
const accessibleSequenceString = (sequence,
|
|
24
|
+
const accessibleSequenceString = (sequence, platform) => splitSequence(sequence).map(chord => accessibleChordString(chord, platform)).join(' then ');
|
|
25
25
|
|
|
26
26
|
export { Sequence, accessibleSequenceString };
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import type { Platform } from './platform';
|
|
1
2
|
/**
|
|
2
3
|
* Short-form iconic versions of keys. These should be intuitive (not archaic) and match icons on keyboards.
|
|
3
4
|
*/
|
|
4
|
-
export declare const condensedKeyName: (key: string,
|
|
5
|
+
export declare const condensedKeyName: (key: string, platform: Platform) => string;
|
|
5
6
|
/**
|
|
6
7
|
* Specific key displays for 'full' format. We still do show some icons (ie punctuation)
|
|
7
8
|
* because that's more intuitive, but for the rest of keys we show the standard key name.
|
|
8
9
|
*/
|
|
9
|
-
export declare const fullKeyName: (key: string,
|
|
10
|
+
export declare const fullKeyName: (key: string, platform: Platform) => string;
|
|
10
11
|
/**
|
|
11
12
|
* Accessible key names intended to be read by a screen reader. This prevents screen
|
|
12
13
|
* readers from expressing punctuation in speech, ie, reading a long pause instead of the
|
|
13
14
|
* word "period".
|
|
14
15
|
*/
|
|
15
|
-
export declare const accessibleKeyName: (key: string,
|
|
16
|
+
export declare const accessibleKeyName: (key: string, platform: Platform) => string;
|
|
16
17
|
//# sourceMappingURL=key-names.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-names.d.ts","sourceRoot":"","sources":["../../src/KeybindingHint/key-names.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"key-names.d.ts","sourceRoot":"","sources":["../../src/KeybindingHint/key-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAA;AAUxC;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,EAAE,UAAU,QAAQ,WAwBpC,CAAA;AAE5B;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,UAAU,QAAQ,WAc/B,CAAA;AAE5B;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,EAAE,UAAU,QAAQ,WAmDnC,CAAA"}
|
|
@@ -12,15 +12,15 @@ const capitalize = ([first, ...rest]) => {
|
|
|
12
12
|
/**
|
|
13
13
|
* Short-form iconic versions of keys. These should be intuitive (not archaic) and match icons on keyboards.
|
|
14
14
|
*/
|
|
15
|
-
const condensedKeyName = (key,
|
|
15
|
+
const condensedKeyName = (key, platform) => {
|
|
16
16
|
var _alt$control$shift$me;
|
|
17
17
|
return (_alt$control$shift$me = {
|
|
18
|
-
alt:
|
|
18
|
+
alt: platform === 'apple' ? '⌥' : 'Alt',
|
|
19
19
|
// the alt key _is_ the option key on MacOS - in the browser there is no "option" key
|
|
20
20
|
control: '⌃',
|
|
21
21
|
shift: '⇧',
|
|
22
|
-
meta:
|
|
23
|
-
mod:
|
|
22
|
+
meta: platform === 'apple' ? '⌘' : platform === 'windows' ? 'Win' : 'Meta',
|
|
23
|
+
mod: platform === 'apple' ? '⌘' : '⌃',
|
|
24
24
|
pageup: 'PgUp',
|
|
25
25
|
pagedown: 'PgDn',
|
|
26
26
|
arrowup: '↑',
|
|
@@ -47,11 +47,12 @@ const condensedKeyName = (key, isMacOS) => {
|
|
|
47
47
|
* Specific key displays for 'full' format. We still do show some icons (ie punctuation)
|
|
48
48
|
* because that's more intuitive, but for the rest of keys we show the standard key name.
|
|
49
49
|
*/
|
|
50
|
-
const fullKeyName = (key,
|
|
51
|
-
var _alt$mod$$
|
|
52
|
-
return (_alt$mod$$
|
|
53
|
-
alt:
|
|
54
|
-
|
|
50
|
+
const fullKeyName = (key, platform) => {
|
|
51
|
+
var _alt$meta$mod$$pageu;
|
|
52
|
+
return (_alt$meta$mod$$pageu = {
|
|
53
|
+
alt: platform === 'apple' ? 'Option' : 'Alt',
|
|
54
|
+
meta: platform === 'apple' ? 'Command' : platform === 'windows' ? 'Windows' : 'Meta',
|
|
55
|
+
mod: platform === 'apple' ? 'Command' : 'Control',
|
|
55
56
|
'+': 'Plus',
|
|
56
57
|
pageup: 'Page Up',
|
|
57
58
|
pagedown: 'Page Down',
|
|
@@ -61,7 +62,7 @@ const fullKeyName = (key, isMacOS) => {
|
|
|
61
62
|
arrowright: 'Right Arrow',
|
|
62
63
|
capslock: 'Caps Lock',
|
|
63
64
|
printscreen: 'Print Screen'
|
|
64
|
-
}[key]) !== null && _alt$mod$$
|
|
65
|
+
}[key]) !== null && _alt$meta$mod$$pageu !== void 0 ? _alt$meta$mod$$pageu : capitalize(key);
|
|
65
66
|
};
|
|
66
67
|
|
|
67
68
|
/**
|
|
@@ -69,12 +70,12 @@ const fullKeyName = (key, isMacOS) => {
|
|
|
69
70
|
* readers from expressing punctuation in speech, ie, reading a long pause instead of the
|
|
70
71
|
* word "period".
|
|
71
72
|
*/
|
|
72
|
-
const accessibleKeyName = (key,
|
|
73
|
+
const accessibleKeyName = (key, platform) => {
|
|
73
74
|
var _alt$meta$mod$pageup$;
|
|
74
75
|
return (_alt$meta$mod$pageup$ = {
|
|
75
|
-
alt:
|
|
76
|
-
meta:
|
|
77
|
-
mod:
|
|
76
|
+
alt: platform === 'apple' ? 'option' : 'alt',
|
|
77
|
+
meta: platform === 'apple' ? 'command' : platform === 'windows' ? 'Windows' : 'meta',
|
|
78
|
+
mod: platform === 'apple' ? 'command' : 'control',
|
|
78
79
|
// Screen readers may not be able to pronounce concatenated words - this provides a better experience
|
|
79
80
|
pageup: 'page up',
|
|
80
81
|
pagedown: 'page down',
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The platform categories that affect how keyboard shortcut keys are displayed.
|
|
3
|
+
*
|
|
4
|
+
* - `apple`: Apple platforms (macOS and iOS/iPadOS), which use the Command and Option keys.
|
|
5
|
+
* - `windows`: Windows, which uses the Windows (Meta) key.
|
|
6
|
+
* - `other`: Any other platform (e.g. Linux, Android), where the Meta key does not map to a
|
|
7
|
+
* consistent label.
|
|
8
|
+
*/
|
|
9
|
+
export type Platform = 'apple' | 'windows' | 'other';
|
|
10
|
+
export declare const PlatformOverrideProvider: import("react").Provider<Platform | null>;
|
|
11
|
+
/**
|
|
12
|
+
* SSR-safe hook for determining the current platform category used when displaying
|
|
13
|
+
* keyboard shortcut keys.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors the approach of `useIsMacOS`: on the client it reads the real value immediately,
|
|
16
|
+
* and on the server it returns a safe default (`'other'`).
|
|
17
|
+
*
|
|
18
|
+
* If a `PlatformOverrideProvider` is present with a non-null value, that value is used
|
|
19
|
+
* instead of the detected platform.
|
|
20
|
+
*/
|
|
21
|
+
export declare function usePlatform(): Platform;
|
|
22
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/KeybindingHint/platform.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAA;AAkCpD,eAAO,MAAM,wBAAwB,2CAAmC,CAAA;AAExE;;;;;;;;;GASG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAItC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { isMacOS } from '@primer/behaviors/utils';
|
|
2
|
+
import { useContext, useSyncExternalStore, createContext } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The platform categories that affect how keyboard shortcut keys are displayed.
|
|
6
|
+
*
|
|
7
|
+
* - `apple`: Apple platforms (macOS and iOS/iPadOS), which use the Command and Option keys.
|
|
8
|
+
* - `windows`: Windows, which uses the Windows (Meta) key.
|
|
9
|
+
* - `other`: Any other platform (e.g. Linux, Android), where the Meta key does not map to a
|
|
10
|
+
* consistent label.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// No-op. The platform never changes at runtime, so there is nothing to
|
|
14
|
+
// subscribe to. Hoisted to avoid creating a new function on every call.
|
|
15
|
+
const subscribe = () => () => {};
|
|
16
|
+
|
|
17
|
+
/** SSR-unsafe detection of iOS/iPadOS (in addition to macOS, which is detected separately). */
|
|
18
|
+
const ssrUnsafeIsIOS = () => {
|
|
19
|
+
if (typeof navigator === 'undefined') return false;
|
|
20
|
+
return /iphone|ipad|ipod/i.test(navigator.platform) || /iphone|ipad|ipod/i.test(navigator.userAgent);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** SSR-unsafe detection of Windows. */
|
|
24
|
+
const ssrUnsafeIsWindows = () => {
|
|
25
|
+
if (typeof navigator === 'undefined') return false;
|
|
26
|
+
return /^win/i.test(navigator.platform);
|
|
27
|
+
};
|
|
28
|
+
const getSnapshot = () => {
|
|
29
|
+
if (isMacOS() || ssrUnsafeIsIOS()) return 'apple';
|
|
30
|
+
if (ssrUnsafeIsWindows()) return 'windows';
|
|
31
|
+
return 'other';
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Safe default for SSR since we can't detect the platform on the server.
|
|
35
|
+
const getServerSnapshot = () => 'other';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Allows overriding the detected platform. This is primarily intended for testing and
|
|
39
|
+
* Storybook, where we want to preview how keyboard hints render on platforms other than the
|
|
40
|
+
* one actually running. A `null` value (the default) means "use the detected platform".
|
|
41
|
+
*/
|
|
42
|
+
const PlatformOverrideContext = /*#__PURE__*/createContext(null);
|
|
43
|
+
PlatformOverrideContext.Provider;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* SSR-safe hook for determining the current platform category used when displaying
|
|
47
|
+
* keyboard shortcut keys.
|
|
48
|
+
*
|
|
49
|
+
* Mirrors the approach of `useIsMacOS`: on the client it reads the real value immediately,
|
|
50
|
+
* and on the server it returns a safe default (`'other'`).
|
|
51
|
+
*
|
|
52
|
+
* If a `PlatformOverrideProvider` is present with a non-null value, that value is used
|
|
53
|
+
* instead of the detected platform.
|
|
54
|
+
*/
|
|
55
|
+
function usePlatform() {
|
|
56
|
+
const override = useContext(PlatformOverrideContext);
|
|
57
|
+
const detected = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
58
|
+
return override !== null && override !== void 0 ? override : detected;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { usePlatform };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../src/TooltipV2/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAiD,KAAK,yBAAyB,EAAC,MAAM,OAAO,CAAA;AAS3G,OAAO,EAAoD,KAAK,mBAAmB,EAAC,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../src/TooltipV2/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAiD,KAAK,yBAAyB,EAAC,MAAM,OAAO,CAAA;AAS3G,OAAO,EAAoD,KAAK,mBAAmB,EAAC,MAAM,mBAAmB,CAAA;AAI7G,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAA;AAE9C,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;AAChF,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,CAAC;IACjD,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa,CAAA;IAC9B,cAAc,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAA;IACjF;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IACnC;;;;;;;;OAQG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACjC,CAAC,GACA,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;AAiEnC,eAAO,MAAM,cAAc;gBAAoC,MAAM;EAAM,CAAA;AAI3E,eAAO,MAAM,OAAO,EAAE,yBAAyB,CAC7C,KAAK,CAAC,eAAe,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CACvE,GACC,UAkSD,CAAA"}
|
|
@@ -5,13 +5,13 @@ import { getAnchoredPosition } from '@primer/behaviors';
|
|
|
5
5
|
import { isSupported, apply } from '@oddbird/popover-polyfill/fn';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
7
7
|
import classes from './Tooltip.module.css.js';
|
|
8
|
+
import { usePlatform } from '../KeybindingHint/platform.js';
|
|
8
9
|
import VisuallyHidden from '../_VisuallyHidden.js';
|
|
9
10
|
import useSafeTimeout from '../hooks/useSafeTimeout.js';
|
|
10
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
11
12
|
import { useId } from '../hooks/useId.js';
|
|
12
13
|
import { useProvidedRefOrCreate } from '../hooks/useProvidedRefOrCreate.js';
|
|
13
14
|
import { useOnEscapePress } from '../hooks/useOnEscapePress.js';
|
|
14
|
-
import { useIsMacOS } from '../hooks/useIsMacOS.js';
|
|
15
15
|
import { getAccessibleKeybindingHintString, KeybindingHint } from '../KeybindingHint/KeybindingHint.js';
|
|
16
16
|
|
|
17
17
|
// map tooltip direction to anchoredPosition props
|
|
@@ -195,7 +195,7 @@ const Tooltip = /*#__PURE__*/React.forwardRef(({
|
|
|
195
195
|
closeTooltip();
|
|
196
196
|
}
|
|
197
197
|
}, [isPopoverOpen]);
|
|
198
|
-
const
|
|
198
|
+
const platform = usePlatform();
|
|
199
199
|
const hasAriaLabel = 'aria-label' in rest;
|
|
200
200
|
|
|
201
201
|
// Normalize keybindingHint to an array for uniform rendering
|
|
@@ -290,7 +290,7 @@ const Tooltip = /*#__PURE__*/React.forwardRef(({
|
|
|
290
290
|
children: [/*#__PURE__*/jsxs("span", {
|
|
291
291
|
id: hasAriaLabel ? undefined : tooltipId,
|
|
292
292
|
children: [text, /*#__PURE__*/jsxs(VisuallyHidden, {
|
|
293
|
-
children: ["(", keybindingHints.map(hint => getAccessibleKeybindingHintString(hint,
|
|
293
|
+
children: ["(", keybindingHints.map(hint => getAccessibleKeybindingHintString(hint, platform)).join(' or '), ")"]
|
|
294
294
|
})]
|
|
295
295
|
}), /*#__PURE__*/jsx("span", {
|
|
296
296
|
className: clsx(classes.KeybindingHintContainer, text && classes.HasTextBefore, keybindingHints.length > 1 && classes.HasMultipleHints),
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.prc-TreeView-TreeViewRootUlStyles-Mzrmj{list-style:none;margin:0;padding:0}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f{outline:none;overflow-clip-margin:var(--base-size-8,.5rem)}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f):focus-visible>div,:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f).focus-visible>div{box-shadow:var(--boxShadow-thick,inset 0 0 0 .125rem) var(--fgColor-accent,#0969da)}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f):focus-visible>div,:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f).focus-visible>div{outline:2px solid HighlightText;outline-offset:-2px}}[data-has-leading-action]:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f){--has-leading-action:1}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ{--level:1;--toggle-width:1rem;--min-item-height:2rem;border-radius:var(--borderRadius-medium,.375rem);color:var(--fgColor-default,#1f2328);cursor:pointer;display:grid;font-size:var(--text-body-size-medium,.875rem);grid-template-areas:"spacer leadingAction toggle content trailingAction";grid-template-columns:var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr auto;overflow-clip-margin:var(--base-size-8,.5rem);position:relative;width:100%;--leading-action-width:calc(var(--has-leading-action, 0)*1.5rem);--spacer-width:calc((var(--level) - 1)*(var(--toggle-width)/2))}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ):hover{background-color:var(--control-transparent-bgColor-hover,#818b981a)}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ):hover{outline:2px solid transparent;outline-offset:-2px}}@media (pointer:coarse){.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ{--toggle-width:1.5rem;--min-item-height:2.75rem}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:where([data-omit-spacer=true]) .prc-TreeView-TreeViewItemContainer-z6qqQ{grid-template-columns:0 0 0 1fr auto}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f:where([data-loading])>.prc-TreeView-TreeViewItemContainer-z6qqQ:hover{background-color:transparent;cursor:default}@media (forced-colors:active){.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f:where([data-loading])>.prc-TreeView-TreeViewItemContainer-z6qqQ:hover{outline:none}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f[aria-current=true]>.prc-TreeView-TreeViewItemContainer-z6qqQ{background-color:var(--control-transparent-bgColor-selected,#818b9826)}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f[aria-current=true]>.prc-TreeView-TreeViewItemContainer-z6qqQ):after{background-color:var(--fgColor-accent,#0969da);border-radius:var(--borderRadius-medium,.375rem);content:"";height:1.5rem;left:calc(var(--base-size-8,.5rem)*-1);position:absolute;top:calc(50% - var(--base-size-12,.75rem));width:.25rem}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f[aria-current=true]>.prc-TreeView-TreeViewItemContainer-z6qqQ):after{background-color:HighlightText}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemToggle-hq3Xq{align-items:flex-start;color:var(--fgColor-muted,#59636e);display:flex;grid-area:toggle;height:100%;justify-content:center;padding-top:calc(var(--min-item-height)/2 - var(--base-size-12,.75rem)/2)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemToggleHover-H9tbt:hover{background-color:var(--control-transparent-bgColor-hover,#818b981a)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemToggleEnd-nWt9I{border-bottom-left-radius:var(--borderRadius-medium,.375rem);border-top-left-radius:var(--borderRadius-medium,.375rem)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContent-RKsCI{display:flex;gap:var(--stack-gap-condensed,.5rem);grid-area:content;height:100%;line-height:var(--custom-line-height,var(--text-body-lineHeight-medium,1.4285));padding:0 var(--base-size-8,.5rem);padding-bottom:calc((var(--min-item-height) - var(--custom-line-height, 1.3rem))/2);padding-top:calc((var(--min-item-height) - var(--custom-line-height, 1.3rem))/2)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContentText-FFaKp{flex:1 1 auto;width:0}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:where([data-truncate-text=true]) .prc-TreeView-TreeViewItemContentText-FFaKp{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:where([data-truncate-text=false]) .prc-TreeView-TreeViewItemContentText-FFaKp{word-break:break-word}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemVisual-naWzj{align-items:center;color:var(--fgColor-muted,#59636e);display:flex;height:var(--custom-line-height,1.3rem)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLeadingAction-vmOIV{color:var(--fgColor-muted,#59636e);display:flex;grid-area:leadingAction}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLeadingAction-vmOIV)>button{flex-shrink:1}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemTrailingAction-h9M5g{color:var(--fgColor-muted,#59636e);display:flex;grid-area:trailingAction}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemTrailingActionButton-pCTdP{flex-shrink:1}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLevelLine-F-0-2{border-right:var(--borderWidth-thin,.0625rem) solid;border-color:var(--tree-line-color,var(--borderColor-muted,#d1d9e0b3));height:100%;width:100%}@media (hover:hover){.prc-TreeView-TreeViewRootUlStyles-Mzrmj{--tree-line-color:transparent}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:focus-within,.prc-TreeView-TreeViewRootUlStyles-Mzrmj:hover{--tree-line-color:var(--borderColor-muted,#d1d9e0b3)}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewDirectoryIcon-yP1oY{color:var(--treeViewItem-leadingVisual-iconColor-rest,#54aeff);display:grid}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewVisuallyHidden-1N8xK{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border-width:0;white-space:nowrap}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd{align-items:center;column-gap:.5rem;display:flex;height:2rem}@media (pointer:coarse){.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd{height:2.75rem}}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+1){--tree-item-loading-width:67%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+2){--tree-item-loading-width:47%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+3){--tree-item-loading-width:73%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+4){--tree-item-loading-width:64%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+5){--tree-item-loading-width:50%}.prc-TreeView-TreeItemSkeletonTextStyles-8VJ-g{width:var(--tree-item-loading-width,67%)}
|
|
2
|
+
/*# sourceMappingURL=TreeView-1bf45a33.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/TreeView/TreeView.module.css.js"],"names":[],"mappings":"AAAA,yCAGE,eAAgB,CADhB,QAAS,CADT,SA8PF,CA7OE,0EAQE,YAAa,CADb,6CAgBF,CAbE,kMAEE,mFAMF,CAJE,8BAJF,kMAKI,+BAAgC,CAChC,mBAEJ,CADE,CAGF,wGACE,sBACF,CAGF,mFACE,SAAU,CACV,mBAAoB,CACpB,sBAAuB,CAcvB,gDAAyC,CAFzC,oCAA6B,CAC7B,cAAe,CAVf,YAAa,CAQb,8CAAuC,CAKvC,wEAAyE,CADzE,kGAAmG,CALnG,6CAAwC,CARxC,iBAAkB,CAElB,UAAW,CAcX,gEAAmE,CACnE,+DAeF,CAbE,8FACE,mEAMF,CAJE,8BAHF,8FAII,6BAA8B,CAC9B,mBAEJ,CADE,CAGF,wBAjCF,mFAkCI,qBAAsB,CACtB,yBAEJ,CADE,CAGF,kHACE,oCACF,CAOA,gJAEE,4BAA6B,CAD7B,cAMF,CAHE,8BAJF,gJAKI,YAEJ,CADE,CAGF,uIACE,sEAwBF,CApBE,kJAaE,8CAAuC,CACvC,gDAAyC,CARzC,UAAW,CADX,aAAc,CAFd,sCAAmC,CAFnC,iBAAkB,CAClB,0CAAoC,CAEpC,YAeF,CAHE,8BAhBF,kJAiBI,8BAEJ,CADE,CAIJ,gFAWE,sBAAuB,CAHvB,kCAA2B,CAP3B,YAAa,CAQb,gBAAiB,CAPjB,WAAY,CAQZ,sBAAuB,CAHvB,yEAKF,CAEA,2FACE,mEACF,CAEA,mFAEE,4DAAqD,CADrD,yDAEF,CAEA,iFACE,YAAa,CAWb,oCAA+B,CAD/B,iBAAkB,CATlB,WAAY,CAQZ,+EAAkF,CAPlF,kCAA6B,CAM7B,mFAAsF,CAFtF,gFAMF,CAEA,qFACE,aAAc,CACd,OACF,CAEA,sHACE,eAAgB,CAChB,sBAAuB,CACvB,kBACF,CAEA,uHAEE,qBACF,CAEA,gFAOE,kBAAmB,CADnB,kCAA2B,CAL3B,YAAa,CAIb,uCAGF,CAEA,uFAEE,kCAA2B,CAD3B,YAAa,CAEb,uBAKF,CAHE,mGACE,aACF,CAGF,wFAEE,kCAA2B,CAD3B,YAAa,CAEb,wBACF,CAEA,8FACE,aACF,CAEA,mFAGE,mDAA2C,CAW3C,sEAA8D,CAZ9D,WAAY,CADZ,UAcF,CAEA,qBApOF,yCAqOI,6BA0BJ,CAxBI,qGAEE,oDACF,CACF,CAEA,mFAEE,8DAAuD,CADvD,YAEF,CAEA,oFAGE,UAAW,CAGX,WAAY,CACZ,eAAgB,CAHhB,SAAU,CAHV,iBAAkB,CAClB,SAAU,CAOV,kBAAsB,CAEtB,cAAe,CADf,kBAEF,CAGF,uDAEE,kBAAmB,CACnB,gBAAkB,CAFlB,YAAa,CAGb,WAyBF,CAvBE,wBANF,uDAOI,cAsBJ,CArBE,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAGF,+CACE,wCACF","file":"TreeView-1bf45a33.css","sourcesContent":[".TreeViewRootUlStyles {\n padding: 0;\n margin: 0;\n list-style: none;\n\n /*\n * WARNING: This is a performance optimization.\n *\n * We define styles for the tree items at the root level of the tree\n * to avoid recomputing the styles for each item when the tree updates.\n * We're sacrificing maintainability for performance because TreeView\n * needs to be performant enough to handle large trees (thousands of items).\n *\n * This is intended to be a temporary solution until we can improve the\n * performance of our styling patterns.\n *\n * Do NOT copy this pattern without understanding the tradeoffs.\n */\n .TreeViewItem {\n /*\n * `overflow-clip-margin` extends the paint clip edge by 8px so the current-item indicator\n * (positioned at `left: -8px` of the row container) remains visible when a consumer applies\n * `contain: paint` (or `contain: strict`, or `content-visibility: auto`) to this `<li>`. Has\n * no effect when no paint containment is active, so default rendering is unchanged.\n */\n overflow-clip-margin: var(--base-size-8);\n outline: none;\n\n &:focus-visible > div,\n &:global(.focus-visible) > div {\n box-shadow: var(--boxShadow-thick) var(--fgColor-accent);\n\n @media (forced-colors: active) {\n outline: 2px solid HighlightText;\n outline-offset: -2px;\n }\n }\n\n &[data-has-leading-action] {\n --has-leading-action: 1;\n }\n }\n\n .TreeViewItemContainer {\n --level: 1;\n --toggle-width: 1rem;\n --min-item-height: 2rem;\n\n position: relative;\n display: grid;\n width: 100%;\n /*\n * Mirrors the `overflow-clip-margin` on `.TreeViewItem` so the indicator also stays\n * visible when `containIntrinsicSize` is set on this row (which sets\n * `content-visibility: auto` on this container and implies paint containment).\n */\n overflow-clip-margin: var(--base-size-8);\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-default);\n cursor: pointer;\n border-radius: var(--borderRadius-medium);\n grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr auto;\n grid-template-areas: 'spacer leadingAction toggle content trailingAction';\n\n --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem);\n --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2));\n\n &:hover {\n background-color: var(--control-transparent-bgColor-hover);\n\n @media (forced-colors: active) {\n outline: 2px solid transparent;\n outline-offset: -2px;\n }\n }\n\n @media (pointer: coarse) {\n --toggle-width: 1.5rem;\n --min-item-height: 2.75rem;\n }\n }\n\n &:where([data-omit-spacer='true']) .TreeViewItemContainer {\n grid-template-columns: 0 0 0 1fr auto;\n }\n\n /*\n * Suppress hover affordances on rows being used as skeleton loading placeholders.\n * Marked positively via `data-loading` from `LoadingItem` so we avoid the broad\n * invalidation cost of `:has(.TreeViewItemSkeleton)` across every row in large trees.\n */\n .TreeViewItem:where([data-loading]) > .TreeViewItemContainer:hover {\n cursor: default;\n background-color: transparent;\n\n @media (forced-colors: active) {\n outline: none;\n }\n }\n\n .TreeViewItem[aria-current='true'] > .TreeViewItemContainer {\n background-color: var(--control-transparent-bgColor-selected);\n\n /* Current item indicator */\n /* stylelint-disable-next-line selector-max-specificity */\n &::after {\n position: absolute;\n top: calc(50% - var(--base-size-12));\n left: calc(-1 * var(--base-size-8));\n width: 0.25rem;\n height: 1.5rem;\n content: '';\n\n /*\n * Use fgColor accent for consistency across all themes. Using the \"correct\" variable,\n * --bgColor-accent-emphasis, causes vrt failures for dark high contrast mode\n */\n /* stylelint-disable-next-line primer/colors */\n background-color: var(--fgColor-accent);\n border-radius: var(--borderRadius-medium);\n\n @media (forced-colors: active) {\n background-color: HighlightText;\n }\n }\n }\n\n .TreeViewItemToggle {\n display: flex;\n height: 100%;\n\n /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc(var(--min-item-height) / 2 - var(--base-size-12) / 2);\n color: var(--fgColor-muted);\n grid-area: toggle;\n justify-content: center;\n align-items: flex-start;\n }\n\n .TreeViewItemToggleHover:hover {\n background-color: var(--control-transparent-bgColor-hover);\n }\n\n .TreeViewItemToggleEnd {\n border-top-left-radius: var(--borderRadius-medium);\n border-bottom-left-radius: var(--borderRadius-medium);\n }\n\n .TreeViewItemContent {\n display: flex;\n height: 100%;\n padding: 0 var(--base-size-8);\n\n /* The dynamic top and bottom padding to maintain the minimum item height for single line items */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n /* stylelint-disable-next-line primer/spacing */\n padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285));\n grid-area: content;\n gap: var(--stack-gap-condensed);\n }\n\n .TreeViewItemContentText {\n flex: 1 1 auto;\n width: 0;\n }\n\n &:where([data-truncate-text='true']) .TreeViewItemContentText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &:where([data-truncate-text='false']) .TreeViewItemContentText {\n /* stylelint-disable-next-line declaration-property-value-keyword-no-deprecated */\n word-break: break-word;\n }\n\n .TreeViewItemVisual {\n display: flex;\n\n /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n height: var(--custom-line-height, 1.3rem);\n color: var(--fgColor-muted);\n align-items: center;\n }\n\n .TreeViewItemLeadingAction {\n display: flex;\n color: var(--fgColor-muted);\n grid-area: leadingAction;\n\n & > button {\n flex-shrink: 1;\n }\n }\n\n .TreeViewItemTrailingAction {\n display: flex;\n color: var(--fgColor-muted);\n grid-area: trailingAction;\n }\n\n .TreeViewItemTrailingActionButton {\n flex-shrink: 1;\n }\n\n .TreeViewItemLevelLine {\n width: 100%;\n height: 100%;\n border-right: var(--borderWidth-thin) solid;\n\n /*\n * `--tree-line-color` is set on the root `<ul>` and inherited down. On coarse pointers it\n * stays unset and falls back to `muted` (lines always visible). On hover-capable devices it\n * is initialized to `transparent` on the root and flipped to `muted` while the tree is\n * hovered or focused, so the browser only has to propagate a single inherited custom\n * property instead of re-matching `.TreeViewItemLevelLine` descendant selectors on every\n * hover/focus change inside large trees.\n */\n /* stylelint-disable-next-line primer/colors -- private custom property, defaults to a Primer token */\n border-color: var(--tree-line-color, var(--borderColor-muted));\n }\n\n @media (hover: hover) {\n --tree-line-color: transparent;\n\n &:hover,\n &:focus-within {\n --tree-line-color: var(--borderColor-muted);\n }\n }\n\n .TreeViewDirectoryIcon {\n display: grid;\n color: var(--treeViewItem-leadingVisual-iconColor-rest);\n }\n\n .TreeViewVisuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n /* stylelint-disable-next-line primer/spacing */\n margin: -1px;\n overflow: hidden;\n /* stylelint-disable-next-line property-no-deprecated */\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n}\n\n.TreeViewSkeletonItemContainerStyle {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n height: 2rem;\n\n @media (pointer: coarse) {\n height: 2.75rem;\n }\n\n &:nth-of-type(5n + 1) {\n --tree-item-loading-width: 67%;\n }\n\n &:nth-of-type(5n + 2) {\n --tree-item-loading-width: 47%;\n }\n\n &:nth-of-type(5n + 3) {\n --tree-item-loading-width: 73%;\n }\n\n &:nth-of-type(5n + 4) {\n --tree-item-loading-width: 64%;\n }\n\n &:nth-of-type(5n + 5) {\n --tree-item-loading-width: 50%;\n }\n}\n\n.TreeItemSkeletonTextStyles {\n width: var(--tree-item-loading-width, 67%);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeView.d.ts","sourceRoot":"","sources":["../../src/TreeView/TreeView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,IAAI,EACV,MAAM,wBAAwB,CAAA;AAE/B,OAAO,KAA+B,MAAM,OAAO,CAAA;AAsBnD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"TreeView.d.ts","sourceRoot":"","sources":["../../src/TreeView/TreeView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,IAAI,EACV,MAAM,wBAAwB,CAAA;AAE/B,OAAO,KAA+B,MAAM,OAAO,CAAA;AAsBnD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,gBAAgB,CAAA;AAiDpD,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAA;IACjD,iBAAiB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAA;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,IAAI,EAAE,IAAI,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAgHD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAA;IACjD,iBAAiB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAA;IAC3D,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACzB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,wBAAwB,EAAE,CAAA;CAC9C,CAAA;AA4QD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAA;AAEnE,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAgND,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE;QAAC,UAAU,EAAE,OAAO,CAAA;KAAC,KAAK,KAAK,CAAC,SAAS,CAAC,CAAA;IAG/E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAqED,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,wBAAwB,EAAE,CAAA;IACjC,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AA0ED,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,wBAAwB,EAAE,CAAA;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAwED,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AA4CD,eAAO,MAAM,QAAQ;;;;;;;;CAQnB,CAAA"}
|
|
@@ -15,9 +15,9 @@ import { useTypeahead } from './useTypeahead.js';
|
|
|
15
15
|
import { IconButton } from '../Button/IconButton.js';
|
|
16
16
|
import { ButtonComponent } from '../Button/Button.js';
|
|
17
17
|
import { ActionList } from '../ActionList/index.js';
|
|
18
|
+
import { usePlatform } from '../KeybindingHint/platform.js';
|
|
18
19
|
import { isSlot } from '../utils/is-slot.js';
|
|
19
20
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
20
|
-
import { useIsMacOS } from '../hooks/useIsMacOS.js';
|
|
21
21
|
import { AriaStatus } from '../live-region/AriaStatus.js';
|
|
22
22
|
import Spinner from '../Spinner/Spinner.js';
|
|
23
23
|
import { Tooltip } from '../TooltipV2/Tooltip.js';
|
|
@@ -46,6 +46,11 @@ const ItemContext = /*#__PURE__*/React.createContext({
|
|
|
46
46
|
trailingActionId: ''
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
// Module-private channel from LoadingItem to the Item it renders. Lets us mark the placeholder
|
|
50
|
+
// row with `data-loading` (used by CSS to suppress hover affordances) without exposing an
|
|
51
|
+
// internal-only prop on the public TreeViewItemProps API.
|
|
52
|
+
const LoadingPlaceholderContext = /*#__PURE__*/React.createContext(false);
|
|
53
|
+
|
|
49
54
|
// ----------------------------------------------------------------------------
|
|
50
55
|
// TreeView
|
|
51
56
|
|
|
@@ -303,6 +308,7 @@ const Item = /*#__PURE__*/React.forwardRef(({
|
|
|
303
308
|
const {
|
|
304
309
|
level
|
|
305
310
|
} = React.useContext(ItemContext);
|
|
311
|
+
const isLoadingPlaceholder = React.useContext(LoadingPlaceholderContext);
|
|
306
312
|
const {
|
|
307
313
|
hasSubTree,
|
|
308
314
|
subTree,
|
|
@@ -311,7 +317,7 @@ const Item = /*#__PURE__*/React.forwardRef(({
|
|
|
311
317
|
const [isSubTreeEmpty, setIsSubTreeEmpty] = React.useState(!hasSubTree);
|
|
312
318
|
const [actionCommandPressed, setActionCommandPressed] = React.useState(false);
|
|
313
319
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
314
|
-
const
|
|
320
|
+
const platform = usePlatform();
|
|
315
321
|
|
|
316
322
|
// Set the expanded state and cache it
|
|
317
323
|
const setIsExpandedWithCache = React.useCallback(
|
|
@@ -372,8 +378,8 @@ const Item = /*#__PURE__*/React.forwardRef(({
|
|
|
372
378
|
}
|
|
373
379
|
}, [onSelect, setIsExpandedWithCache, toggle, activateActionsDialog]);
|
|
374
380
|
const ariaDescribedByIds = [slots.leadingVisual ? leadingVisualId : null, slots.trailingVisual ? trailingVisualId : null].filter(Boolean);
|
|
375
|
-
const shortcut = `Shift+${
|
|
376
|
-
const trailingActionShortcutText = `Press (${getAccessibleKeybindingHintString(shortcut,
|
|
381
|
+
const shortcut = `Shift+${platform === 'apple' ? 'Meta' : 'Control'}+U`;
|
|
382
|
+
const trailingActionShortcutText = `Press (${getAccessibleKeybindingHintString(shortcut, platform)}) for more actions.`;
|
|
377
383
|
return /*#__PURE__*/jsx(ItemContext.Provider, {
|
|
378
384
|
value: {
|
|
379
385
|
itemId,
|
|
@@ -400,6 +406,7 @@ const Item = /*#__PURE__*/React.forwardRef(({
|
|
|
400
406
|
"aria-current": isCurrentItem ? 'true' : undefined,
|
|
401
407
|
"aria-selected": isFocused ? 'true' : 'false',
|
|
402
408
|
"data-has-leading-action": slots.leadingAction ? true : undefined,
|
|
409
|
+
"data-loading": isLoadingPlaceholder ? true : undefined,
|
|
403
410
|
onKeyDown: handleKeyDown,
|
|
404
411
|
onFocus: event_1 => {
|
|
405
412
|
// Defer scroll to the next animation frame so that rapid keyboard
|
|
@@ -778,10 +785,13 @@ const LoadingItem = /*#__PURE__*/React.forwardRef((t0, ref) => {
|
|
|
778
785
|
}
|
|
779
786
|
let t4;
|
|
780
787
|
if ($[5] !== itemId || $[6] !== ref || $[7] !== t1 || $[8] !== t3) {
|
|
781
|
-
t4 = /*#__PURE__*/
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
788
|
+
t4 = /*#__PURE__*/jsx(LoadingPlaceholderContext.Provider, {
|
|
789
|
+
value: true,
|
|
790
|
+
children: /*#__PURE__*/jsxs(Item, {
|
|
791
|
+
id: itemId,
|
|
792
|
+
ref: ref,
|
|
793
|
+
children: [t1, t3]
|
|
794
|
+
})
|
|
785
795
|
});
|
|
786
796
|
$[5] = itemId;
|
|
787
797
|
$[6] = ref;
|
|
@@ -813,10 +823,13 @@ const LoadingItem = /*#__PURE__*/React.forwardRef((t0, ref) => {
|
|
|
813
823
|
}
|
|
814
824
|
let t3;
|
|
815
825
|
if ($[12] !== itemId || $[13] !== ref) {
|
|
816
|
-
t3 = /*#__PURE__*/
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
826
|
+
t3 = /*#__PURE__*/jsx(LoadingPlaceholderContext.Provider, {
|
|
827
|
+
value: true,
|
|
828
|
+
children: /*#__PURE__*/jsxs(Item, {
|
|
829
|
+
id: itemId,
|
|
830
|
+
ref: ref,
|
|
831
|
+
children: [t1, t2]
|
|
832
|
+
})
|
|
820
833
|
});
|
|
821
834
|
$[12] = itemId;
|
|
822
835
|
$[13] = ref;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import './TreeView-
|
|
1
|
+
import './TreeView-1bf45a33.css';
|
|
2
2
|
|
|
3
|
-
var classes = {"TreeViewRootUlStyles":"prc-TreeView-TreeViewRootUlStyles-Mzrmj","TreeViewItem":"prc-TreeView-TreeViewItem-Ter5f","TreeViewItemContainer":"prc-TreeView-TreeViewItemContainer-z6qqQ","
|
|
3
|
+
var classes = {"TreeViewRootUlStyles":"prc-TreeView-TreeViewRootUlStyles-Mzrmj","TreeViewItem":"prc-TreeView-TreeViewItem-Ter5f","TreeViewItemContainer":"prc-TreeView-TreeViewItemContainer-z6qqQ","TreeViewItemToggle":"prc-TreeView-TreeViewItemToggle-hq3Xq","TreeViewItemToggleHover":"prc-TreeView-TreeViewItemToggleHover-H9tbt","TreeViewItemToggleEnd":"prc-TreeView-TreeViewItemToggleEnd-nWt9I","TreeViewItemContent":"prc-TreeView-TreeViewItemContent-RKsCI","TreeViewItemContentText":"prc-TreeView-TreeViewItemContentText-FFaKp","TreeViewItemVisual":"prc-TreeView-TreeViewItemVisual-naWzj","TreeViewItemLeadingAction":"prc-TreeView-TreeViewItemLeadingAction-vmOIV","TreeViewItemTrailingAction":"prc-TreeView-TreeViewItemTrailingAction-h9M5g","TreeViewItemTrailingActionButton":"prc-TreeView-TreeViewItemTrailingActionButton-pCTdP","TreeViewItemLevelLine":"prc-TreeView-TreeViewItemLevelLine-F-0-2","TreeViewDirectoryIcon":"prc-TreeView-TreeViewDirectoryIcon-yP1oY","TreeViewVisuallyHidden":"prc-TreeView-TreeViewVisuallyHidden-1N8xK","TreeViewSkeletonItemContainerStyle":"prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd","TreeItemSkeletonTextStyles":"prc-TreeView-TreeItemSkeletonTextStyles-8VJ-g"};
|
|
4
4
|
|
|
5
5
|
export { classes as default };
|
|
@@ -3831,6 +3831,10 @@
|
|
|
3831
3831
|
{
|
|
3832
3832
|
"id": "experimental-components-keybindinghint-features--on-primary",
|
|
3833
3833
|
"code": "(args) => (\n <div className={classes.PrimaryBackground}>\n <KeybindingHint {...args} />\n </div>\n)"
|
|
3834
|
+
},
|
|
3835
|
+
{
|
|
3836
|
+
"id": "experimental-components-keybindinghint-features--platforms",
|
|
3837
|
+
"code": "({ format = 'full', ...args }) => (\n <table className={classes.PlatformTable}>\n <thead>\n <tr>\n <th\n scope=\"col\"\n className={`${classes.PlatformCell} ${classes.PlatformHeader}`}\n >\n Platform\n </th>\n {modifierKeys.map((key) => (\n <th\n scope=\"col\"\n className={`${classes.PlatformCell} ${classes.PlatformHeader}`}\n key={key}\n >\n {key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {platforms.map(({ platform, label }) => (\n <tr key={platform}>\n <th\n scope=\"row\"\n className={`${classes.PlatformCell} ${classes.PlatformHeader}`}\n >\n {label}\n </th>\n {modifierKeys.map((key) => (\n <td key={key} className={classes.PlatformCell}>\n <PlatformOverrideProvider value={platform}>\n <KeybindingHint {...args} format={format} keys={`${key}+K`} />\n </PlatformOverrideProvider>\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n)"
|
|
3834
3838
|
}
|
|
3835
3839
|
],
|
|
3836
3840
|
"importPath": "@primer/react",
|
package/package.json
CHANGED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
.prc-TreeView-TreeViewRootUlStyles-Mzrmj{list-style:none;margin:0;padding:0}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f{outline:none}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f):focus-visible>div,:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f).focus-visible>div{box-shadow:var(--boxShadow-thick,inset 0 0 0 .125rem) var(--fgColor-accent,#0969da)}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f):focus-visible>div,:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f).focus-visible>div{outline:2px solid HighlightText;outline-offset:-2}}[data-has-leading-action]:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f){--has-leading-action:1}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ{--level:1;--toggle-width:1rem;--min-item-height:2rem;border-radius:var(--borderRadius-medium,.375rem);color:var(--fgColor-default,#1f2328);cursor:pointer;display:grid;font-size:var(--text-body-size-medium,.875rem);grid-template-areas:"spacer leadingAction toggle content trailingAction";grid-template-columns:var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr;position:relative;width:100%;--leading-action-width:calc(var(--has-leading-action, 0)*1.5rem);--spacer-width:calc((var(--level) - 1)*(var(--toggle-width)/2))}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ):hover{background-color:var(--control-transparent-bgColor-hover,#818b981a)}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ):hover{outline:2px solid transparent;outline-offset:-2px}}@media (pointer:coarse){.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ{--toggle-width:1.5rem;--min-item-height:2.75rem}}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ):has(.prc-TreeView-TreeViewItemSkeleton-FGlnx):hover{background-color:transparent;cursor:default}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContainer-z6qqQ):has(.prc-TreeView-TreeViewItemSkeleton-FGlnx):hover{outline:none}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:where([data-omit-spacer=true]) .prc-TreeView-TreeViewItemContainer-z6qqQ{grid-template-columns:0 0 0 1fr}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f[aria-current=true]>.prc-TreeView-TreeViewItemContainer-z6qqQ{background-color:var(--control-transparent-bgColor-selected,#818b9826)}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f[aria-current=true]>.prc-TreeView-TreeViewItemContainer-z6qqQ):after{background-color:var(--fgColor-accent,#0969da);border-radius:var(--borderRadius-medium,.375rem);content:"";height:1.5rem;left:calc(var(--base-size-8,.5rem)*-1);position:absolute;top:calc(50% - var(--base-size-12,.75rem));width:.25rem}@media (forced-colors:active){:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItem-Ter5f[aria-current=true]>.prc-TreeView-TreeViewItemContainer-z6qqQ):after{background-color:HighlightText}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemToggle-hq3Xq{align-items:flex-start;color:var(--fgColor-muted,#59636e);display:flex;grid-area:toggle;height:100%;justify-content:center;padding-top:calc(var(--min-item-height)/2 - var(--base-size-12,.75rem)/2)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemToggleHover-H9tbt:hover{background-color:var(--control-transparent-bgColor-hover,#818b981a)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemToggleEnd-nWt9I{border-bottom-left-radius:var(--borderRadius-medium,.375rem);border-top-left-radius:var(--borderRadius-medium,.375rem)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContent-RKsCI{display:flex;gap:var(--stack-gap-condensed,.5rem);grid-area:content;height:100%;line-height:var(--custom-line-height,var(--text-body-lineHeight-medium,1.4285));padding:0 var(--base-size-8,.5rem);padding-bottom:calc((var(--min-item-height) - var(--custom-line-height, 1.3rem))/2);padding-top:calc((var(--min-item-height) - var(--custom-line-height, 1.3rem))/2)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemContentText-FFaKp{flex:1 1 auto;width:0}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:where([data-truncate-text=true]) .prc-TreeView-TreeViewItemContentText-FFaKp{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:where([data-truncate-text=false]) .prc-TreeView-TreeViewItemContentText-FFaKp{word-break:break-word}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemVisual-naWzj{align-items:center;color:var(--fgColor-muted,#59636e);display:flex;height:var(--custom-line-height,1.3rem)}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLeadingAction-vmOIV{color:var(--fgColor-muted,#59636e);display:flex;grid-area:leadingAction}:is(.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLeadingAction-vmOIV)>button{flex-shrink:1}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemTrailingAction-h9M5g{color:var(--fgColor-muted,#59636e);display:flex;grid-area:trailingAction}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemTrailingActionButton-pCTdP{flex-shrink:1}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLevelLine-F-0-2{border-color:var(--borderColor-muted,#d1d9e0b3);border-right:var(--borderWidth-thin,.0625rem) solid;height:100%;width:100%}@media (hover:hover){.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewItemLevelLine-F-0-2{border-color:transparent}.prc-TreeView-TreeViewRootUlStyles-Mzrmj:focus-within .prc-TreeView-TreeViewItemLevelLine-F-0-2,.prc-TreeView-TreeViewRootUlStyles-Mzrmj:hover .prc-TreeView-TreeViewItemLevelLine-F-0-2{border-color:var(--borderColor-muted,#d1d9e0b3)}}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewDirectoryIcon-yP1oY{color:var(--treeViewItem-leadingVisual-iconColor-rest,#54aeff);display:grid}.prc-TreeView-TreeViewRootUlStyles-Mzrmj .prc-TreeView-TreeViewVisuallyHidden-1N8xK{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border-width:0;white-space:nowrap}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd{align-items:center;column-gap:.5rem;display:flex;height:2rem}@media (pointer:coarse){.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd{height:2.75rem}}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+1){--tree-item-loading-width:67%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+2){--tree-item-loading-width:47%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+3){--tree-item-loading-width:73%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+4){--tree-item-loading-width:64%}.prc-TreeView-TreeViewSkeletonItemContainerStyle-lKqwd:nth-of-type(5n+5){--tree-item-loading-width:50%}.prc-TreeView-TreeItemSkeletonTextStyles-8VJ-g{width:var(--tree-item-loading-width,67%)}
|
|
2
|
-
/*# sourceMappingURL=TreeView-0fe09f34.css.map */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/TreeView/TreeView.module.css.js"],"names":[],"mappings":"AAAA,yCAGE,eAAgB,CADhB,QAAS,CADT,SAsPF,CArOE,0EACE,YAgBF,CAdE,kMAEE,mFAOF,CALE,8BAJF,kMAKI,+BAAgC,CAEhC,iBAEJ,CADE,CAGF,wGACE,sBACF,CAGF,mFACE,SAAU,CACV,mBAAoB,CACpB,sBAAuB,CAQvB,gDAAyC,CAFzC,oCAA6B,CAC7B,cAAe,CAJf,YAAa,CAEb,8CAAuC,CAKvC,wEAAyE,CADzE,6FAA8F,CAP9F,iBAAkB,CAElB,UAAW,CAQX,gEAAmE,CACnE,+DA8BF,CA5BE,8FACE,mEAMF,CAJE,8BAHF,8FAII,6BAA8B,CAC9B,mBAEJ,CADE,CAGF,wBA3BF,mFA4BI,qBAAsB,CACtB,yBAiBJ,CAhBE,CAQA,4IAEE,4BAA6B,CAD7B,cAMF,CAHE,8BAJF,4IAKI,YAEJ,CADE,CAIJ,kHACE,+BACF,CAEA,uIACE,sEAwBF,CApBE,kJAaE,8CAAuC,CACvC,gDAAyC,CARzC,UAAW,CADX,aAAc,CAFd,sCAAmC,CAFnC,iBAAkB,CAClB,0CAAoC,CAEpC,YAeF,CAHE,8BAhBF,kJAiBI,8BAEJ,CADE,CAIJ,gFAWE,sBAAuB,CAHvB,kCAA2B,CAP3B,YAAa,CAQb,gBAAiB,CAPjB,WAAY,CAQZ,sBAAuB,CAHvB,yEAKF,CAEA,2FACE,mEACF,CAEA,mFAEE,4DAAqD,CADrD,yDAEF,CAEA,iFACE,YAAa,CAWb,oCAA+B,CAD/B,iBAAkB,CATlB,WAAY,CAQZ,+EAAkF,CAPlF,kCAA6B,CAM7B,mFAAsF,CAFtF,gFAMF,CAEA,qFACE,aAAc,CACd,OACF,CAEA,sHACE,eAAgB,CAChB,sBAAuB,CACvB,kBACF,CAEA,uHAEE,qBACF,CAEA,gFAOE,kBAAmB,CADnB,kCAA2B,CAL3B,YAAa,CAIb,uCAGF,CAEA,uFAEE,kCAA2B,CAD3B,YAAa,CAEb,uBAKF,CAHE,mGACE,aACF,CAGF,wFAEE,kCAA2B,CAD3B,YAAa,CAEb,wBACF,CAEA,8FACE,aACF,CAEA,mFAQE,+CAAsC,CACtC,mDAA2C,CAP3C,WAAY,CADZ,UASF,CAQA,qBACE,mFACE,wBACF,CAEA,yLAEE,+CACF,CACF,CAEA,mFAEE,8DAAuD,CADvD,YAEF,CAEA,oFAGE,UAAW,CAGX,WAAY,CACZ,eAAgB,CAHhB,SAAU,CAHV,iBAAkB,CAClB,SAAU,CAOV,kBAAsB,CAEtB,cAAe,CADf,kBAEF,CAGF,uDAEE,kBAAmB,CACnB,gBAAkB,CAFlB,YAAa,CAGb,WAyBF,CAvBE,wBANF,uDAOI,cAsBJ,CArBE,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAEA,yEACE,6BACF,CAGF,+CACE,wCACF","file":"TreeView-0fe09f34.css","sourcesContent":[".TreeViewRootUlStyles {\n padding: 0;\n margin: 0;\n list-style: none;\n\n /*\n * WARNING: This is a performance optimization.\n *\n * We define styles for the tree items at the root level of the tree\n * to avoid recomputing the styles for each item when the tree updates.\n * We're sacrificing maintainability for performance because TreeView\n * needs to be performant enough to handle large trees (thousands of items).\n *\n * This is intended to be a temporary solution until we can improve the\n * performance of our styling patterns.\n *\n * Do NOT copy this pattern without understanding the tradeoffs.\n */\n .TreeViewItem {\n outline: none;\n\n &:focus-visible > div,\n &:global(.focus-visible) > div {\n box-shadow: var(--boxShadow-thick) var(--fgColor-accent);\n\n @media (forced-colors: active) {\n outline: 2px solid HighlightText;\n /* stylelint-disable-next-line declaration-property-value-no-unknown */\n outline-offset: -2;\n }\n }\n\n &[data-has-leading-action] {\n --has-leading-action: 1;\n }\n }\n\n .TreeViewItemContainer {\n --level: 1;\n --toggle-width: 1rem;\n --min-item-height: 2rem;\n\n position: relative;\n display: grid;\n width: 100%;\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-default);\n cursor: pointer;\n border-radius: var(--borderRadius-medium);\n grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr;\n grid-template-areas: 'spacer leadingAction toggle content trailingAction';\n\n --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem);\n --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2));\n\n &:hover {\n background-color: var(--control-transparent-bgColor-hover);\n\n @media (forced-colors: active) {\n outline: 2px solid transparent;\n outline-offset: -2px;\n }\n }\n\n @media (pointer: coarse) {\n --toggle-width: 1.5rem;\n --min-item-height: 2.75rem;\n }\n\n /*\n * NOTE: Uses descendant :has() - TreeViewItemSkeleton is nested inside\n * TreeViewItemContent > TreeViewItemContentText, not a direct child.\n * This is acceptable as the search is scoped to this element's subtree.\n */\n /* stylelint-disable-next-line selector-pseudo-class-disallowed-list -- scoped to CSS Module, audited (github/github-ui#17224) */\n &:has(.TreeViewItemSkeleton):hover {\n cursor: default;\n background-color: transparent;\n\n @media (forced-colors: active) {\n outline: none;\n }\n }\n }\n\n &:where([data-omit-spacer='true']) .TreeViewItemContainer {\n grid-template-columns: 0 0 0 1fr;\n }\n\n .TreeViewItem[aria-current='true'] > .TreeViewItemContainer {\n background-color: var(--control-transparent-bgColor-selected);\n\n /* Current item indicator */\n /* stylelint-disable-next-line selector-max-specificity */\n &::after {\n position: absolute;\n top: calc(50% - var(--base-size-12));\n left: calc(-1 * var(--base-size-8));\n width: 0.25rem;\n height: 1.5rem;\n content: '';\n\n /*\n * Use fgColor accent for consistency across all themes. Using the \"correct\" variable,\n * --bgColor-accent-emphasis, causes vrt failures for dark high contrast mode\n */\n /* stylelint-disable-next-line primer/colors */\n background-color: var(--fgColor-accent);\n border-radius: var(--borderRadius-medium);\n\n @media (forced-colors: active) {\n background-color: HighlightText;\n }\n }\n }\n\n .TreeViewItemToggle {\n display: flex;\n height: 100%;\n\n /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc(var(--min-item-height) / 2 - var(--base-size-12) / 2);\n color: var(--fgColor-muted);\n grid-area: toggle;\n justify-content: center;\n align-items: flex-start;\n }\n\n .TreeViewItemToggleHover:hover {\n background-color: var(--control-transparent-bgColor-hover);\n }\n\n .TreeViewItemToggleEnd {\n border-top-left-radius: var(--borderRadius-medium);\n border-bottom-left-radius: var(--borderRadius-medium);\n }\n\n .TreeViewItemContent {\n display: flex;\n height: 100%;\n padding: 0 var(--base-size-8);\n\n /* The dynamic top and bottom padding to maintain the minimum item height for single line items */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n /* stylelint-disable-next-line primer/spacing */\n padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285));\n grid-area: content;\n gap: var(--stack-gap-condensed);\n }\n\n .TreeViewItemContentText {\n flex: 1 1 auto;\n width: 0;\n }\n\n &:where([data-truncate-text='true']) .TreeViewItemContentText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &:where([data-truncate-text='false']) .TreeViewItemContentText {\n /* stylelint-disable-next-line declaration-property-value-keyword-no-deprecated */\n word-break: break-word;\n }\n\n .TreeViewItemVisual {\n display: flex;\n\n /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n height: var(--custom-line-height, 1.3rem);\n color: var(--fgColor-muted);\n align-items: center;\n }\n\n .TreeViewItemLeadingAction {\n display: flex;\n color: var(--fgColor-muted);\n grid-area: leadingAction;\n\n & > button {\n flex-shrink: 1;\n }\n }\n\n .TreeViewItemTrailingAction {\n display: flex;\n color: var(--fgColor-muted);\n grid-area: trailingAction;\n }\n\n .TreeViewItemTrailingActionButton {\n flex-shrink: 1;\n }\n\n .TreeViewItemLevelLine {\n width: 100%;\n height: 100%;\n\n /*\n * On devices without hover, the nesting indicator lines\n * appear at all times.\n */\n border-color: var(--borderColor-muted);\n border-right: var(--borderWidth-thin) solid;\n }\n\n /*\n * On devices with :hover support, the nesting indicator lines\n * fade in when the user mouses over the entire component,\n * or when there's focus inside the component. This makes\n * sure the component remains simple when not in use.\n */\n @media (hover: hover) {\n .TreeViewItemLevelLine {\n border-color: transparent;\n }\n\n &:hover .TreeViewItemLevelLine,\n &:focus-within .TreeViewItemLevelLine {\n border-color: var(--borderColor-muted);\n }\n }\n\n .TreeViewDirectoryIcon {\n display: grid;\n color: var(--treeViewItem-leadingVisual-iconColor-rest);\n }\n\n .TreeViewVisuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n /* stylelint-disable-next-line primer/spacing */\n margin: -1px;\n overflow: hidden;\n /* stylelint-disable-next-line property-no-deprecated */\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n}\n\n.TreeViewSkeletonItemContainerStyle {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n height: 2rem;\n\n @media (pointer: coarse) {\n height: 2.75rem;\n }\n\n &:nth-of-type(5n + 1) {\n --tree-item-loading-width: 67%;\n }\n\n &:nth-of-type(5n + 2) {\n --tree-item-loading-width: 47%;\n }\n\n &:nth-of-type(5n + 3) {\n --tree-item-loading-width: 73%;\n }\n\n &:nth-of-type(5n + 4) {\n --tree-item-loading-width: 64%;\n }\n\n &:nth-of-type(5n + 5) {\n --tree-item-loading-width: 50%;\n }\n}\n\n.TreeItemSkeletonTextStyles {\n width: var(--tree-item-loading-width, 67%);\n}\n"]}
|
package/dist/hooks/useIsMacOS.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { isMacOS } from '@primer/behaviors/utils';
|
|
2
|
-
import { useSyncExternalStore } from 'react';
|
|
3
|
-
|
|
4
|
-
// No-op. The platform never changes at runtime, so there is nothing to
|
|
5
|
-
// subscribe to. Hoisted to avoid creating a new function on every call.
|
|
6
|
-
const subscribe = () => () => {};
|
|
7
|
-
|
|
8
|
-
// Safe default for SSR since we can't detect the platform on the server.
|
|
9
|
-
const getServerSnapshot = () => false;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* SSR-safe hook for determining if the current platform is MacOS.
|
|
13
|
-
*
|
|
14
|
-
* Uses `useSyncExternalStore` to read the platform value:
|
|
15
|
-
*
|
|
16
|
-
* - On the **client**, `ssrUnsafeIsMacOS` reads `navigator.userAgent` and
|
|
17
|
-
* returns the real value immediately, with no extra render pass.
|
|
18
|
-
*
|
|
19
|
-
* - On the **server**, returns `false`. During hydration, if the snapshots
|
|
20
|
-
* differ, React handles the mismatch internally in a single synchronous
|
|
21
|
-
* pass, avoiding the layout shift that a deferred `useEffect` + `setState`
|
|
22
|
-
* would cause.
|
|
23
|
-
*
|
|
24
|
-
* Previous implementation used `useState` + `useEffect`, which caused an
|
|
25
|
-
* unconditional second render on every mount (even on the client where the
|
|
26
|
-
* initial value was already correct).
|
|
27
|
-
*/
|
|
28
|
-
function useIsMacOS() {
|
|
29
|
-
return useSyncExternalStore(subscribe, isMacOS, getServerSnapshot);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export { useIsMacOS };
|