@primer/react 38.6.3-rc.f8f5fddc3 → 38.7.0-rc.b626e5d83
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.
Potentially problematic release.
This version of @primer/react might be problematic. Click here for more details.
- package/CHANGELOG.md +48 -1
- package/dist/ActionBar/ActionBar.d.ts +8 -0
- package/dist/ActionBar/ActionBar.d.ts.map +1 -1
- package/dist/ActionBar/ActionBar.js +83 -53
- package/dist/ActionBar/index.d.ts +1 -0
- package/dist/ActionBar/index.d.ts.map +1 -1
- package/dist/Autocomplete/Autocomplete.d.ts +0 -3
- package/dist/Autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist/Autocomplete/Autocomplete.js +69 -23
- package/dist/Autocomplete/AutocompleteContext.d.ts +23 -3
- package/dist/Autocomplete/AutocompleteContext.d.ts.map +1 -1
- package/dist/Autocomplete/AutocompleteContext.js +20 -1
- package/dist/Autocomplete/AutocompleteInput.d.ts.map +1 -1
- package/dist/Autocomplete/AutocompleteInput.js +8 -5
- package/dist/Autocomplete/AutocompleteMenu.d.ts.map +1 -1
- package/dist/Autocomplete/AutocompleteMenu.js +123 -121
- package/dist/{BaseStyles-79fd37c4.css → BaseStyles-7e59cc50.css} +2 -2
- package/dist/BaseStyles-7e59cc50.css.map +1 -0
- package/dist/BaseStyles.module.css.js +1 -1
- package/dist/Dialog/{Dialog-1a61e61a.css → Dialog-92b5e3b7.css} +2 -2
- package/dist/Dialog/Dialog-92b5e3b7.css.map +1 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +21 -5
- package/dist/Dialog/Dialog.module.css.js +1 -1
- package/dist/FeatureFlags/DefaultFeatureFlags.d.ts.map +1 -1
- package/dist/FeatureFlags/DefaultFeatureFlags.js +1 -0
- package/dist/FeatureFlags/FeatureFlags.d.ts +6 -0
- package/dist/FeatureFlags/FeatureFlags.d.ts.map +1 -1
- package/dist/FeatureFlags/FeatureFlags.js +41 -32
- package/dist/FilteredActionList/FilteredActionList.d.ts +6 -1
- package/dist/FilteredActionList/FilteredActionList.d.ts.map +1 -1
- package/dist/FilteredActionList/FilteredActionList.js +4 -2
- package/dist/PageLayout/{PageLayout-c092f3db.css → PageLayout-51007c87.css} +2 -2
- package/dist/PageLayout/PageLayout-51007c87.css.map +1 -0
- package/dist/PageLayout/PageLayout.d.ts.map +1 -1
- package/dist/PageLayout/PageLayout.js +399 -313
- package/dist/PageLayout/PageLayout.module.css.js +1 -1
- package/dist/PageLayout/paneUtils.d.ts +11 -0
- package/dist/PageLayout/paneUtils.d.ts.map +1 -0
- package/dist/PageLayout/paneUtils.js +34 -0
- package/dist/PageLayout/usePaneWidth.d.ts +2 -1
- package/dist/PageLayout/usePaneWidth.d.ts.map +1 -1
- package/dist/PageLayout/usePaneWidth.js +56 -44
- package/dist/SelectPanel/SelectPanel.d.ts +6 -1
- package/dist/SelectPanel/SelectPanel.d.ts.map +1 -1
- package/dist/SelectPanel/SelectPanel.js +3 -1
- package/dist/TextInput/TextInput-dff8f842.css +2 -0
- package/dist/TextInput/TextInput-dff8f842.css.map +1 -0
- package/dist/TextInput/TextInput.d.ts +5 -0
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +125 -51
- package/dist/TextInput/TextInput.module.css.js +5 -0
- package/dist/Textarea/{TextArea-54099020.css → TextArea-53e27580.css} +2 -2
- package/dist/Textarea/TextArea-53e27580.css.map +1 -0
- package/dist/Textarea/TextArea.module.css.js +2 -2
- package/dist/Textarea/Textarea.d.ts +10 -0
- package/dist/Textarea/Textarea.d.ts.map +1 -1
- package/dist/Textarea/Textarea.js +215 -69
- package/dist/ToggleSwitch/ToggleSwitch-40bab513.css +2 -0
- package/dist/ToggleSwitch/ToggleSwitch-40bab513.css.map +1 -0
- package/dist/ToggleSwitch/ToggleSwitch.module.css.js +1 -1
- package/dist/hooks/useFocusZone.d.ts +4 -0
- package/dist/hooks/useFocusZone.d.ts.map +1 -1
- package/dist/internal/utils/hasInteractiveNodes.d.ts.map +1 -1
- package/dist/internal/utils/hasInteractiveNodes.js +22 -16
- package/dist/utils/__tests__/character-counter.test.d.ts +2 -0
- package/dist/utils/__tests__/character-counter.test.d.ts.map +1 -0
- package/dist/utils/character-counter.d.ts +27 -0
- package/dist/utils/character-counter.d.ts.map +1 -0
- package/dist/utils/character-counter.js +65 -0
- package/generated/components.json +16 -0
- package/package.json +9 -9
- package/dist/BaseStyles-79fd37c4.css.map +0 -1
- package/dist/Dialog/Dialog-1a61e61a.css.map +0 -1
- package/dist/PageLayout/PageLayout-c092f3db.css.map +0 -1
- package/dist/Textarea/TextArea-54099020.css.map +0 -1
- package/dist/ToggleSwitch/ToggleSwitch-d1bd60b0.css +0 -2
- package/dist/ToggleSwitch/ToggleSwitch-d1bd60b0.css.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import './PageLayout-
|
|
1
|
+
import './PageLayout-51007c87.css';
|
|
2
2
|
|
|
3
3
|
var classes = {"paneMaxWidthDiffBreakpoint":"1280","paneMaxWidthDiffDefault":"511","PageLayoutRoot":"prc-PageLayout-PageLayoutRoot--KH-d","PageLayoutWrapper":"prc-PageLayout-PageLayoutWrapper-2BhU2","PageLayoutContent":"prc-PageLayout-PageLayoutContent-BneH9","HorizontalDivider":"prc-PageLayout-HorizontalDivider-JLVqp","VerticalDivider":"prc-PageLayout-VerticalDivider-9QRmK","Header":"prc-PageLayout-Header-0of-R","HeaderContent":"prc-PageLayout-HeaderContent-gdFfN","HeaderHorizontalDivider":"prc-PageLayout-HeaderHorizontalDivider-odAHl","ContentWrapper":"prc-PageLayout-ContentWrapper-gR9eG","Content":"prc-PageLayout-Content-xWL-A","PaneWrapper":"prc-PageLayout-PaneWrapper-pHPop","PaneVerticalDivider":"prc-PageLayout-PaneVerticalDivider-le57g","Pane":"prc-PageLayout-Pane-AyzHK","PaneHorizontalDivider":"prc-PageLayout-PaneHorizontalDivider-9tbnE","FooterWrapper":"prc-PageLayout-FooterWrapper-9cB8y","FooterHorizontalDivider":"prc-PageLayout-FooterHorizontalDivider-W-RaS","FooterContent":"prc-PageLayout-FooterContent-HUS0V","DraggableHandle":"prc-PageLayout-DraggableHandle-9s6B4"};
|
|
4
4
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type DraggingStylesParams = {
|
|
2
|
+
handle: HTMLElement | null;
|
|
3
|
+
pane: HTMLElement | null;
|
|
4
|
+
contentWrapper: HTMLElement | null;
|
|
5
|
+
};
|
|
6
|
+
/** Apply visual feedback and performance optimizations during drag */
|
|
7
|
+
export declare function setDraggingStyles({ handle, pane, contentWrapper }: DraggingStylesParams): void;
|
|
8
|
+
/** Remove drag styles and restore normal state */
|
|
9
|
+
export declare function removeDraggingStyles({ handle, pane, contentWrapper }: DraggingStylesParams): void;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=paneUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paneUtils.d.ts","sourceRoot":"","sources":["../../src/PageLayout/paneUtils.ts"],"names":[],"mappings":"AAAA,KAAK,oBAAoB,GAAG;IAC1B,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IAC1B,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,cAAc,EAAE,WAAW,GAAG,IAAI,CAAA;CACnC,CAAA;AAID,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,EAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAC,EAAE,oBAAoB,QAWrF;AAED,kDAAkD;AAClD,wBAAgB,oBAAoB,CAAC,EAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAC,EAAE,oBAAoB,QAOxF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const DATA_DRAGGING_ATTR = 'data-dragging';
|
|
2
|
+
|
|
3
|
+
/** Apply visual feedback and performance optimizations during drag */
|
|
4
|
+
function setDraggingStyles({
|
|
5
|
+
handle,
|
|
6
|
+
pane,
|
|
7
|
+
contentWrapper
|
|
8
|
+
}) {
|
|
9
|
+
// Handle visual feedback (must be inline for instant response)
|
|
10
|
+
// Use CSS variable to control ::before pseudo-element background color.
|
|
11
|
+
// This avoids cascade conflicts between inline styles and pseudo-element backgrounds.
|
|
12
|
+
handle === null || handle === void 0 ? void 0 : handle.style.setProperty('--draggable-handle--bg-color', 'var(--bgColor-accent-emphasis)');
|
|
13
|
+
handle === null || handle === void 0 ? void 0 : handle.style.setProperty('--draggable-handle--drag-opacity', '1');
|
|
14
|
+
handle === null || handle === void 0 ? void 0 : handle.style.setProperty('--draggable-handle--transition', 'none');
|
|
15
|
+
|
|
16
|
+
// Set attribute for CSS containment (O(1) direct selector, not descendant)
|
|
17
|
+
pane === null || pane === void 0 ? void 0 : pane.setAttribute(DATA_DRAGGING_ATTR, 'true');
|
|
18
|
+
contentWrapper === null || contentWrapper === void 0 ? void 0 : contentWrapper.setAttribute(DATA_DRAGGING_ATTR, 'true');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Remove drag styles and restore normal state */
|
|
22
|
+
function removeDraggingStyles({
|
|
23
|
+
handle,
|
|
24
|
+
pane,
|
|
25
|
+
contentWrapper
|
|
26
|
+
}) {
|
|
27
|
+
handle === null || handle === void 0 ? void 0 : handle.style.removeProperty('--draggable-handle--bg-color');
|
|
28
|
+
handle === null || handle === void 0 ? void 0 : handle.style.removeProperty('--draggable-handle--drag-opacity');
|
|
29
|
+
handle === null || handle === void 0 ? void 0 : handle.style.removeProperty('--draggable-handle--transition');
|
|
30
|
+
pane === null || pane === void 0 ? void 0 : pane.removeAttribute(DATA_DRAGGING_ATTR);
|
|
31
|
+
contentWrapper === null || contentWrapper === void 0 ? void 0 : contentWrapper.removeAttribute(DATA_DRAGGING_ATTR);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { removeDraggingStyles, setDraggingStyles };
|
|
@@ -13,6 +13,7 @@ export type UsePaneWidthOptions = {
|
|
|
13
13
|
widthStorageKey: string;
|
|
14
14
|
paneRef: React.RefObject<HTMLDivElement | null>;
|
|
15
15
|
handleRef: React.RefObject<HTMLDivElement | null>;
|
|
16
|
+
contentWrapperRef: React.RefObject<HTMLDivElement | null>;
|
|
16
17
|
};
|
|
17
18
|
export type UsePaneWidthResult = {
|
|
18
19
|
/** Current width for React state (used in ARIA attributes) */
|
|
@@ -66,6 +67,6 @@ export declare const updateAriaValues: (handle: HTMLElement | null, values: {
|
|
|
66
67
|
* Handles initialization from storage, clamping on viewport resize, and provides
|
|
67
68
|
* functions to save and reset width.
|
|
68
69
|
*/
|
|
69
|
-
export declare function usePaneWidth({ width, minWidth, resizable, widthStorageKey, paneRef, handleRef, }: UsePaneWidthOptions): UsePaneWidthResult;
|
|
70
|
+
export declare function usePaneWidth({ width, minWidth, resizable, widthStorageKey, paneRef, handleRef, contentWrapperRef, }: UsePaneWidthOptions): UsePaneWidthResult;
|
|
70
71
|
export {};
|
|
71
72
|
//# sourceMappingURL=usePaneWidth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePaneWidth.d.ts","sourceRoot":"","sources":["../../src/PageLayout/usePaneWidth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAA;AAQ5C,KAAK,WAAW,GAAG,GAAG,MAAM,IAAI,CAAA;AAEhC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,WAAW,CAAA;IAChB,OAAO,EAAE,WAAW,CAAA;IACpB,GAAG,EAAE,WAAW,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEpD,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,SAAS,GAAG,kBAAkB,CAAA;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IAC/C,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"usePaneWidth.d.ts","sourceRoot":"","sources":["../../src/PageLayout/usePaneWidth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAA;AAQ5C,KAAK,WAAW,GAAG,GAAG,MAAM,IAAI,CAAA;AAEhC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,WAAW,CAAA;IAChB,OAAO,EAAE,WAAW,CAAA;IACpB,GAAG,EAAE,WAAW,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEpD,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,SAAS,GAAG,kBAAkB,CAAA;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IAC/C,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACjD,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;CAC1D,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAA;IACpB,wDAAwD;IACxD,eAAe,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC/C,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,eAAe,EAAE,MAAM,MAAM,CAAA;IAC7B,yDAAyD;IACzD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,6BAA6B;IAC7B,eAAe,EAAE,MAAM,MAAM,CAAA;CAC9B,CAAA;AAKD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,QAA6C,CAAA;AAIhF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC;;;GAGG;AACH,eAAO,MAAM,cAAc,IAAI,CAAA;AAE/B,6CAA6C;AAC7C,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAyC,CAAA;AAKhG,eAAO,MAAM,oBAAoB,GAAI,OAAO,SAAS,GAAG,kBAAkB,KAAG,KAAK,IAAI,kBAGrF,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,SAAS,GAAG,kBAAkB,KAAG,KAAK,IAAI,SAE5E,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,GAAG,SAAS,GAAG,kBAAkB,KAAG,MAOvE,CAAA;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAI3E;AAID,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,WAAW,GAAG,IAAI,EAC1B,QAAQ;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAC,SASvD,CAAA;AAKD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,SAAS,EACT,eAAe,EACf,OAAO,EACP,SAAS,EACT,iBAAiB,GAClB,EAAE,mBAAmB,GAAG,kBAAkB,CA2M1C"}
|
|
@@ -44,7 +44,7 @@ const isCustomWidthOptions = width => {
|
|
|
44
44
|
return width.default !== undefined;
|
|
45
45
|
};
|
|
46
46
|
const isPaneWidth = width => {
|
|
47
|
-
return
|
|
47
|
+
return width === 'small' || width === 'medium' || width === 'large';
|
|
48
48
|
};
|
|
49
49
|
const getDefaultPaneWidth = w => {
|
|
50
50
|
if (isPaneWidth(w)) {
|
|
@@ -92,7 +92,8 @@ function usePaneWidth({
|
|
|
92
92
|
resizable,
|
|
93
93
|
widthStorageKey,
|
|
94
94
|
paneRef,
|
|
95
|
-
handleRef
|
|
95
|
+
handleRef,
|
|
96
|
+
contentWrapperRef
|
|
96
97
|
}) {
|
|
97
98
|
// Derive constraints from width configuration
|
|
98
99
|
const isCustomWidth = isCustomWidthOptions(width);
|
|
@@ -145,7 +146,10 @@ function usePaneWidth({
|
|
|
145
146
|
const getDefaultWidth = React.useCallback(() => getDefaultPaneWidth(width), [width]);
|
|
146
147
|
const saveWidth = React.useCallback(value => {
|
|
147
148
|
currentWidthRef.current = value;
|
|
148
|
-
|
|
149
|
+
// Visual update already done via inline styles - React state sync is non-urgent
|
|
150
|
+
startTransition(() => {
|
|
151
|
+
setCurrentWidth(value);
|
|
152
|
+
});
|
|
149
153
|
try {
|
|
150
154
|
localStorage.setItem(widthStorageKey, value.toString());
|
|
151
155
|
} catch {
|
|
@@ -161,24 +165,15 @@ function usePaneWidth({
|
|
|
161
165
|
});
|
|
162
166
|
|
|
163
167
|
// Update CSS variable, refs, and ARIA on mount and window resize.
|
|
164
|
-
// Strategy:
|
|
165
|
-
// 1. Throttled (16ms): Update --pane-max-width CSS variable for immediate visual clamp
|
|
166
|
-
// 2. Debounced (150ms): Sync refs, ARIA, and React state when resize stops
|
|
168
|
+
// Strategy: Only sync when resize stops (debounced) to avoid layout thrashing on large DOMs
|
|
167
169
|
useIsomorphicLayoutEffect(() => {
|
|
168
|
-
var _paneRef$
|
|
170
|
+
var _paneRef$current3;
|
|
169
171
|
if (!resizable) return;
|
|
170
172
|
let lastViewportWidth = window.innerWidth;
|
|
171
173
|
|
|
172
|
-
// Quick CSS-only update for immediate visual feedback (throttled)
|
|
173
|
-
const updateCSSOnly = () => {
|
|
174
|
-
var _paneRef$current;
|
|
175
|
-
const actualMax = getMaxPaneWidthRef.current();
|
|
176
|
-
(_paneRef$current = paneRef.current) === null || _paneRef$current === void 0 ? void 0 : _paneRef$current.style.setProperty('--pane-max-width', `${actualMax}px`);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
174
|
// Full sync of refs, ARIA, and state (debounced, runs when resize stops)
|
|
180
175
|
const syncAll = () => {
|
|
181
|
-
var _paneRef$
|
|
176
|
+
var _paneRef$current;
|
|
182
177
|
const currentViewportWidth = window.innerWidth;
|
|
183
178
|
|
|
184
179
|
// Only call getComputedStyle if we crossed the breakpoint (expensive)
|
|
@@ -187,30 +182,30 @@ function usePaneWidth({
|
|
|
187
182
|
if (crossedBreakpoint) {
|
|
188
183
|
maxWidthDiffRef.current = getPaneMaxWidthDiff(paneRef.current);
|
|
189
184
|
}
|
|
190
|
-
const
|
|
185
|
+
const actualMax = getMaxPaneWidthRef.current();
|
|
191
186
|
|
|
192
187
|
// Update CSS variable for visual clamping (may already be set by throttled update)
|
|
193
|
-
(_paneRef$
|
|
188
|
+
(_paneRef$current = paneRef.current) === null || _paneRef$current === void 0 ? void 0 : _paneRef$current.style.setProperty('--pane-max-width', `${actualMax}px`);
|
|
194
189
|
|
|
195
190
|
// Track if we clamped current width
|
|
196
|
-
const wasClamped = currentWidthRef.current >
|
|
191
|
+
const wasClamped = currentWidthRef.current > actualMax;
|
|
197
192
|
if (wasClamped) {
|
|
198
|
-
var _paneRef$
|
|
199
|
-
currentWidthRef.current =
|
|
200
|
-
(_paneRef$
|
|
193
|
+
var _paneRef$current2;
|
|
194
|
+
currentWidthRef.current = actualMax;
|
|
195
|
+
(_paneRef$current2 = paneRef.current) === null || _paneRef$current2 === void 0 ? void 0 : _paneRef$current2.style.setProperty('--pane-width', `${actualMax}px`);
|
|
201
196
|
}
|
|
202
197
|
|
|
203
198
|
// Update ARIA via DOM - cheap, no React re-render
|
|
204
199
|
updateAriaValues(handleRef.current, {
|
|
205
|
-
max:
|
|
200
|
+
max: actualMax,
|
|
206
201
|
current: currentWidthRef.current
|
|
207
202
|
});
|
|
208
203
|
|
|
209
204
|
// Defer state updates so parent re-renders see accurate values
|
|
210
205
|
startTransition(() => {
|
|
211
|
-
setMaxPaneWidth(
|
|
206
|
+
setMaxPaneWidth(actualMax);
|
|
212
207
|
if (wasClamped) {
|
|
213
|
-
setCurrentWidth(
|
|
208
|
+
setCurrentWidth(actualMax);
|
|
214
209
|
}
|
|
215
210
|
});
|
|
216
211
|
};
|
|
@@ -219,7 +214,7 @@ function usePaneWidth({
|
|
|
219
214
|
maxWidthDiffRef.current = getPaneMaxWidthDiff(paneRef.current);
|
|
220
215
|
const initialMax = getMaxPaneWidthRef.current();
|
|
221
216
|
setMaxPaneWidth(initialMax);
|
|
222
|
-
(_paneRef$
|
|
217
|
+
(_paneRef$current3 = paneRef.current) === null || _paneRef$current3 === void 0 ? void 0 : _paneRef$current3.style.setProperty('--pane-max-width', `${initialMax}px`);
|
|
223
218
|
updateAriaValues(handleRef.current, {
|
|
224
219
|
min: minPaneWidth,
|
|
225
220
|
max: initialMax,
|
|
@@ -229,35 +224,51 @@ function usePaneWidth({
|
|
|
229
224
|
// For custom widths, max is fixed - no need to listen to resize
|
|
230
225
|
if (customMaxWidth !== null) return;
|
|
231
226
|
|
|
232
|
-
// Throttle
|
|
233
|
-
|
|
234
|
-
const
|
|
227
|
+
// Throttle approach for window resize - provides immediate visual feedback for small DOMs
|
|
228
|
+
// while still limiting update frequency
|
|
229
|
+
const THROTTLE_MS = 16; // ~60fps
|
|
230
|
+
const DEBOUNCE_MS = 150; // Delay before removing containment after resize stops
|
|
231
|
+
let lastUpdateTime = 0;
|
|
232
|
+
let pendingUpdate = false;
|
|
235
233
|
let rafId = null;
|
|
236
234
|
let debounceId = null;
|
|
237
|
-
let
|
|
235
|
+
let isResizing = false;
|
|
236
|
+
const startResizeOptimizations = () => {
|
|
237
|
+
var _paneRef$current4, _contentWrapperRef$cu;
|
|
238
|
+
if (isResizing) return;
|
|
239
|
+
isResizing = true;
|
|
240
|
+
(_paneRef$current4 = paneRef.current) === null || _paneRef$current4 === void 0 ? void 0 : _paneRef$current4.setAttribute('data-dragging', 'true');
|
|
241
|
+
(_contentWrapperRef$cu = contentWrapperRef.current) === null || _contentWrapperRef$cu === void 0 ? void 0 : _contentWrapperRef$cu.setAttribute('data-dragging', 'true');
|
|
242
|
+
};
|
|
243
|
+
const endResizeOptimizations = () => {
|
|
244
|
+
var _paneRef$current5, _contentWrapperRef$cu2;
|
|
245
|
+
if (!isResizing) return;
|
|
246
|
+
isResizing = false;
|
|
247
|
+
(_paneRef$current5 = paneRef.current) === null || _paneRef$current5 === void 0 ? void 0 : _paneRef$current5.removeAttribute('data-dragging');
|
|
248
|
+
(_contentWrapperRef$cu2 = contentWrapperRef.current) === null || _contentWrapperRef$cu2 === void 0 ? void 0 : _contentWrapperRef$cu2.removeAttribute('data-dragging');
|
|
249
|
+
};
|
|
238
250
|
const handleResize = () => {
|
|
251
|
+
// Apply containment on first resize event (stays applied until resize stops)
|
|
252
|
+
startResizeOptimizations();
|
|
239
253
|
const now = Date.now();
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} else if (rafId === null) {
|
|
246
|
-
// Schedule next frame if we're within throttle window
|
|
254
|
+
if (now - lastUpdateTime >= THROTTLE_MS) {
|
|
255
|
+
lastUpdateTime = now;
|
|
256
|
+
syncAll();
|
|
257
|
+
} else if (!pendingUpdate) {
|
|
258
|
+
pendingUpdate = true;
|
|
247
259
|
rafId = requestAnimationFrame(() => {
|
|
260
|
+
pendingUpdate = false;
|
|
248
261
|
rafId = null;
|
|
249
|
-
|
|
250
|
-
|
|
262
|
+
lastUpdateTime = Date.now();
|
|
263
|
+
syncAll();
|
|
251
264
|
});
|
|
252
265
|
}
|
|
253
266
|
|
|
254
|
-
//
|
|
255
|
-
if (debounceId !== null)
|
|
256
|
-
clearTimeout(debounceId);
|
|
257
|
-
}
|
|
267
|
+
// Debounce the cleanup — remove containment after resize stops
|
|
268
|
+
if (debounceId !== null) clearTimeout(debounceId);
|
|
258
269
|
debounceId = setTimeout(() => {
|
|
259
270
|
debounceId = null;
|
|
260
|
-
|
|
271
|
+
endResizeOptimizations();
|
|
261
272
|
}, DEBOUNCE_MS);
|
|
262
273
|
};
|
|
263
274
|
|
|
@@ -266,9 +277,10 @@ function usePaneWidth({
|
|
|
266
277
|
return () => {
|
|
267
278
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
268
279
|
if (debounceId !== null) clearTimeout(debounceId);
|
|
280
|
+
endResizeOptimizations();
|
|
269
281
|
window.removeEventListener('resize', handleResize);
|
|
270
282
|
};
|
|
271
|
-
}, [resizable, customMaxWidth, minPaneWidth, paneRef, handleRef]);
|
|
283
|
+
}, [resizable, customMaxWidth, minPaneWidth, paneRef, handleRef, contentWrapperRef]);
|
|
272
284
|
return {
|
|
273
285
|
currentWidth,
|
|
274
286
|
currentWidthRef,
|
|
@@ -50,6 +50,11 @@ interface SelectPanelBaseProps {
|
|
|
50
50
|
*/
|
|
51
51
|
disableFullscreenOnNarrow?: boolean;
|
|
52
52
|
showSelectAll?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Set to true to allow focus to move to elements that are dynamically prepended to the container.
|
|
55
|
+
* Default is false.
|
|
56
|
+
*/
|
|
57
|
+
focusPrependedElements?: boolean;
|
|
53
58
|
}
|
|
54
59
|
type SelectPanelVariantProps = {
|
|
55
60
|
variant?: 'anchored';
|
|
@@ -59,7 +64,7 @@ type SelectPanelVariantProps = {
|
|
|
59
64
|
onCancel: () => void;
|
|
60
65
|
};
|
|
61
66
|
export type SelectPanelProps = SelectPanelBaseProps & Omit<FilteredActionListProps, 'selectionVariant' | 'variant' | 'message'> & Pick<AnchoredOverlayProps, 'open' | 'height' | 'width' | 'align'> & AnchoredOverlayWrapperAnchorProps & (SelectPanelSingleSelection | SelectPanelMultiSelection) & SelectPanelVariantProps;
|
|
62
|
-
declare function Panel({ open, onOpenChange, renderAnchor, anchorRef: externalAnchorRef, placeholder, placeholderText, inputLabel, selected, title, subtitle, onSelectedChange, filterValue: externalFilterValue, onFilterChange: externalOnFilterChange, items, footer, textInputProps, overlayProps, loading, initialLoadingType, className, height, width, id, message, notice, onCancel, variant, secondaryAction, showSelectedOptionsFirst, disableFullscreenOnNarrow, align, showSelectAll, ...listProps }: SelectPanelProps): JSX.Element;
|
|
67
|
+
declare function Panel({ open, onOpenChange, renderAnchor, anchorRef: externalAnchorRef, placeholder, placeholderText, inputLabel, selected, title, subtitle, onSelectedChange, filterValue: externalFilterValue, onFilterChange: externalOnFilterChange, items, footer, textInputProps, overlayProps, loading, initialLoadingType, className, height, width, id, message, notice, onCancel, variant, secondaryAction, showSelectedOptionsFirst, disableFullscreenOnNarrow, align, showSelectAll, focusPrependedElements, ...listProps }: SelectPanelProps): JSX.Element;
|
|
63
68
|
declare const SecondaryButton: React.FC<ButtonProps>;
|
|
64
69
|
declare const SecondaryLink: React.FC<LinkButtonProps & ButtonProps>;
|
|
65
70
|
export declare const SelectPanel: typeof Panel & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectPanel.d.ts","sourceRoot":"","sources":["../../src/SelectPanel/SelectPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAC,MAAM,wBAAwB,CAAA;AAC1F,OAAO,KAAK,EAAE,EAA+E,KAAK,GAAG,EAAC,MAAM,OAAO,CAAA;AACnH,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,oBAAoB,CAAA;AAE5D,OAAO,KAAK,EAAC,iCAAiC,EAAC,MAAM,oCAAoC,CAAA;AACzF,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,uBAAuB,CAAA;AAGlE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAA;AAE5C,OAAO,KAAK,EAAY,SAAS,EAAC,MAAM,IAAI,CAAA;AAiB5C,OAAO,KAAK,EAAC,WAAW,EAAE,eAAe,EAAC,MAAM,iBAAiB,CAAA;AAiCjE,UAAU,0BAA0B;IAClC,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAA;IAC/B,gBAAgB,EAAE,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAA;CAC5D;AAED,UAAU,yBAAyB;IACjC,QAAQ,EAAE,SAAS,EAAE,CAAA;IACrB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;CAClD;AAED,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,UAAU,CAAA;AACvD,MAAM,MAAM,0BAA0B,GAClC,KAAK,CAAC,YAAY,CAAC,OAAO,eAAe,CAAC,GAC1C,KAAK,CAAC,YAAY,CAAC,OAAO,aAAa,CAAC,CAAA;AAE5C,UAAU,oBAAoB;IAG5B,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;IAExC,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;IAC3C,YAAY,EAAE,CACZ,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,cAAc,GAAG,kBAAkB,GAAG,eAAe,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,KAC/F,IAAI,CAAA;IACT,eAAe,CAAC,EAAE,0BAA0B,CAAA;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IACpC,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE;QAEP,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QACtC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;KACtC,CAAA;IACD,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;QAEb,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QACtC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;QACtC,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;QAErC,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;KACjC,CAAA;IACD;;OAEG;IAEH,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;IACzC,wBAAwB,CAAC,EAAE,OAAO,CAAA;IAClC;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,aAAa,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"SelectPanel.d.ts","sourceRoot":"","sources":["../../src/SelectPanel/SelectPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -107,6 +107,7 @@ function Panel({
|
|
|
107
107
|
disableFullscreenOnNarrow,
|
|
108
108
|
align,
|
|
109
109
|
showSelectAll = false,
|
|
110
|
+
focusPrependedElements,
|
|
110
111
|
...listProps
|
|
111
112
|
}) {
|
|
112
113
|
var _listProps$groupMetad;
|
|
@@ -679,7 +680,8 @@ function Panel({
|
|
|
679
680
|
description: typeof (message === null || message === void 0 ? void 0 : message.body) === 'string' ? message.body : EMPTY_MESSAGE.description
|
|
680
681
|
},
|
|
681
682
|
fullScreenOnNarrow: usingFullScreenOnNarrow,
|
|
682
|
-
className: clsx(className, classes.FilteredActionList)
|
|
683
|
+
className: clsx(className, classes.FilteredActionList),
|
|
684
|
+
focusPrependedElements: focusPrependedElements
|
|
683
685
|
}), footer ? /*#__PURE__*/jsx("div", {
|
|
684
686
|
className: classes.Footer,
|
|
685
687
|
children: footer
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.prc-TextInput-CharacterCounter-vJZBe{align-items:center;color:var(--fgColor-muted,var(--color-fg-muted));display:flex;gap:var(--control-xsmall-gap,.25rem)}.prc-TextInput-CharacterCounter--error-HA0kN{color:var(--fgColor-danger,var(--color-danger-fg))}
|
|
2
|
+
/*# sourceMappingURL=TextInput-dff8f842.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/TextInput/TextInput.module.css.js"],"names":[],"mappings":"AAAA,sCAEE,kBAAmB,CAEnB,gDAA2B,CAH3B,YAAa,CAEb,oCAEF,CAEA,6CACE,kDACF","file":"TextInput-dff8f842.css","sourcesContent":[".CharacterCounter {\n display: flex;\n align-items: center;\n gap: var(--control-xsmall-gap);\n color: var(--fgColor-muted);\n}\n\n.CharacterCounter--error {\n color: var(--fgColor-danger);\n}\n"]}
|
|
@@ -28,6 +28,11 @@ export type TextInputNonPassthroughProps = {
|
|
|
28
28
|
* A visual that renders inside the input after the typing area
|
|
29
29
|
*/
|
|
30
30
|
trailingAction?: React.ReactElement<React.HTMLProps<HTMLButtonElement>>;
|
|
31
|
+
/**
|
|
32
|
+
* Optional character limit for the input. If provided, a character counter will be displayed below the input.
|
|
33
|
+
* When the limit is exceeded, validation styling will be applied.
|
|
34
|
+
*/
|
|
35
|
+
characterLimit?: number;
|
|
31
36
|
} & Partial<Pick<StyledWrapperProps, 'block' | 'contrast' | 'disabled' | 'monospace' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size' | 'validationStatus'>>;
|
|
32
37
|
export type TextInputProps = Merge<React.ComponentPropsWithoutRef<'input'>, TextInputNonPassthroughProps>;
|
|
33
38
|
declare const _default: PolymorphicForwardRefComponent<"input", TextInputProps> & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../src/TextInput/TextInput.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../src/TextInput/TextInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAAwD,MAAM,OAAO,CAAA;AAE5E,OAAO,KAAK,EAAC,mBAAmB,IAAI,8BAA8B,EAAC,MAAM,sBAAsB,CAAA;AAO/F,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,yCAAyC,CAAA;AAQ/E,MAAM,MAAM,4BAA4B,GAAG;IACzC,uEAAuE;IACvE,IAAI,CAAC,EAAE,KAAK,CAAC,WAAW,CAAA;IACxB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;QAKI;IACJ,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAA;IAChD,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,SAAS,CAAA;IACnD;;OAEG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,SAAS,CAAA;IACpD;;OAEG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACvE;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,OAAO,CACT,IAAI,CACF,kBAAkB,EAChB,OAAO,GACP,UAAU,GACV,UAAU,GACV,WAAW,GACX,OAAO,GACP,UAAU,GACV,UAAU,GACV,SAAS,GACT,MAAM,GACN,kBAAkB,CACrB,CACF,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,4BAA4B,CAAC,CAAA;;;;;;;;;;;AAiOzG,wBAGE"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import React, { useState, useId, useCallback } from 'react';
|
|
1
|
+
import React, { useState, useRef, useId, useCallback, useEffect } from 'react';
|
|
2
2
|
import { isValidElementType } from 'react-is';
|
|
3
3
|
import { clsx } from 'clsx';
|
|
4
|
+
import { AlertFillIcon } from '@primer/octicons-react';
|
|
5
|
+
import classes from './TextInput.module.css.js';
|
|
4
6
|
import TextInputInnerVisualSlot from '../internal/components/TextInputInnerVisualSlot.js';
|
|
5
7
|
import { TextInputWrapper } from '../internal/components/TextInputWrapper.js';
|
|
6
8
|
import TextInputAction from '../internal/components/TextInputInnerAction.js';
|
|
7
9
|
import UnstyledTextInput from '../internal/components/UnstyledTextInput.js';
|
|
8
10
|
import VisuallyHidden from '../_VisuallyHidden.js';
|
|
9
|
-
import {
|
|
11
|
+
import { CharacterCounter } from '../utils/character-counter.js';
|
|
12
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
10
13
|
import { useProvidedRefOrCreate } from '../hooks/useProvidedRefOrCreate.js';
|
|
14
|
+
import Text from '../Text/Text.js';
|
|
11
15
|
|
|
12
16
|
// using forwardRef is important so that other components can autofocus the input
|
|
13
17
|
const TextInput = /*#__PURE__*/React.forwardRef(({
|
|
@@ -35,10 +39,19 @@ const TextInput = /*#__PURE__*/React.forwardRef(({
|
|
|
35
39
|
// end deprecated props
|
|
36
40
|
type = 'text',
|
|
37
41
|
required,
|
|
42
|
+
characterLimit,
|
|
43
|
+
onChange,
|
|
44
|
+
value,
|
|
45
|
+
defaultValue,
|
|
38
46
|
...inputProps
|
|
39
47
|
}, ref) => {
|
|
40
48
|
const [isInputFocused, setIsInputFocused] = useState(false);
|
|
41
49
|
const inputRef = useProvidedRefOrCreate(ref);
|
|
50
|
+
const [characterCount, setCharacterCount] = useState('');
|
|
51
|
+
const [isOverLimit, setIsOverLimit] = useState(false);
|
|
52
|
+
const [screenReaderMessage, setScreenReaderMessage] = useState('');
|
|
53
|
+
const characterCounterRef = useRef(null);
|
|
54
|
+
|
|
42
55
|
// this class is necessary to style FilterSearch, plz no touchy!
|
|
43
56
|
const wrapperClasses = clsx(className, 'TextInput-wrapper');
|
|
44
57
|
const showLeadingLoadingIndicator = loading && (loaderPosition === 'leading' || Boolean(LeadingVisual && loaderPosition !== 'trailing'));
|
|
@@ -65,56 +78,117 @@ const TextInput = /*#__PURE__*/React.forwardRef(({
|
|
|
65
78
|
setIsInputFocused(false);
|
|
66
79
|
onBlur && onBlur(e_1);
|
|
67
80
|
}, [onBlur]);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
81
|
+
|
|
82
|
+
// Initialize character counter
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (characterLimit) {
|
|
85
|
+
characterCounterRef.current = new CharacterCounter({
|
|
86
|
+
onCountUpdate: (count, overLimit, message) => {
|
|
87
|
+
setCharacterCount(message);
|
|
88
|
+
setIsOverLimit(overLimit);
|
|
89
|
+
},
|
|
90
|
+
onScreenReaderAnnounce: message_0 => {
|
|
91
|
+
setScreenReaderMessage(message_0);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return () => {
|
|
95
|
+
var _characterCounterRef$;
|
|
96
|
+
(_characterCounterRef$ = characterCounterRef.current) === null || _characterCounterRef$ === void 0 ? void 0 : _characterCounterRef$.cleanup();
|
|
97
|
+
characterCounterRef.current = null;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}, [characterLimit]);
|
|
101
|
+
|
|
102
|
+
// Update character count when value changes or on mount
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (characterLimit && characterCounterRef.current) {
|
|
105
|
+
const currentValue = value !== undefined ? String(value) : defaultValue !== undefined ? String(defaultValue) : '';
|
|
106
|
+
characterCounterRef.current.updateCharacterCount(currentValue.length, characterLimit);
|
|
107
|
+
}
|
|
108
|
+
}, [value, defaultValue, characterLimit]);
|
|
109
|
+
|
|
110
|
+
// Handle input change with character counter
|
|
111
|
+
const handleInputChange = useCallback(e_2 => {
|
|
112
|
+
if (characterLimit && characterCounterRef.current) {
|
|
113
|
+
characterCounterRef.current.updateCharacterCount(e_2.target.value.length, characterLimit);
|
|
114
|
+
}
|
|
115
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(e_2);
|
|
116
|
+
}, [onChange, characterLimit]);
|
|
117
|
+
const characterCountId = useId();
|
|
118
|
+
const characterCountStaticMessageId = useId();
|
|
119
|
+
const isValid = isOverLimit ? 'error' : validationStatus;
|
|
120
|
+
return /*#__PURE__*/jsxs(Fragment, {
|
|
121
|
+
children: [/*#__PURE__*/jsxs(TextInputWrapper, {
|
|
122
|
+
block: block,
|
|
123
|
+
className: wrapperClasses,
|
|
124
|
+
validationStatus: isValid,
|
|
125
|
+
contrast: contrast,
|
|
98
126
|
disabled: disabled,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
monospace: monospace,
|
|
128
|
+
size: sizeProp,
|
|
129
|
+
width: widthProp,
|
|
130
|
+
minWidth: minWidthProp,
|
|
131
|
+
maxWidth: maxWidthProp,
|
|
132
|
+
variant: variantProp,
|
|
133
|
+
hasLeadingVisual: Boolean(LeadingVisual || showLeadingLoadingIndicator),
|
|
134
|
+
hasTrailingVisual: Boolean(TrailingVisual || showTrailingLoadingIndicator),
|
|
135
|
+
hasTrailingAction: Boolean(trailingAction),
|
|
136
|
+
isInputFocused: isInputFocused,
|
|
137
|
+
onClick: focusInput,
|
|
138
|
+
"aria-busy": Boolean(loading),
|
|
139
|
+
children: [IconComponent && /*#__PURE__*/jsx(IconComponent, {
|
|
140
|
+
className: "TextInput-icon"
|
|
141
|
+
}), /*#__PURE__*/jsx(TextInputInnerVisualSlot, {
|
|
142
|
+
visualPosition: "leading",
|
|
143
|
+
showLoadingIndicator: showLeadingLoadingIndicator,
|
|
144
|
+
hasLoadingIndicator: typeof loading === 'boolean',
|
|
145
|
+
id: leadingVisualId,
|
|
146
|
+
children: typeof LeadingVisual !== 'string' && isValidElementType(LeadingVisual) ? /*#__PURE__*/jsx(LeadingVisual, {}) : LeadingVisual
|
|
147
|
+
}), /*#__PURE__*/jsx(UnstyledTextInput
|
|
148
|
+
// @ts-expect-error it needs a non nullable ref
|
|
149
|
+
, {
|
|
150
|
+
ref: inputRef,
|
|
151
|
+
disabled: disabled,
|
|
152
|
+
onFocus: handleInputFocus,
|
|
153
|
+
onBlur: handleInputBlur,
|
|
154
|
+
onChange: handleInputChange,
|
|
155
|
+
type: type,
|
|
156
|
+
"aria-required": required,
|
|
157
|
+
"aria-invalid": isValid === 'error' ? 'true' : undefined,
|
|
158
|
+
value: value,
|
|
159
|
+
defaultValue: defaultValue,
|
|
160
|
+
...inputProps,
|
|
161
|
+
"aria-describedby": characterLimit ? [characterCountStaticMessageId, inputDescribedBy].filter(Boolean).join(' ') || undefined : inputDescribedBy,
|
|
162
|
+
"data-component": "input"
|
|
163
|
+
}), loading && /*#__PURE__*/jsx(VisuallyHidden, {
|
|
164
|
+
id: loadingId,
|
|
165
|
+
children: loaderText
|
|
166
|
+
}), /*#__PURE__*/jsx(TextInputInnerVisualSlot, {
|
|
167
|
+
visualPosition: "trailing",
|
|
168
|
+
showLoadingIndicator: showTrailingLoadingIndicator,
|
|
169
|
+
hasLoadingIndicator: typeof loading === 'boolean',
|
|
170
|
+
id: trailingVisualId,
|
|
171
|
+
"data-testid": "text-input-trailing-visual",
|
|
172
|
+
children: typeof TrailingVisual !== 'string' && isValidElementType(TrailingVisual) ? /*#__PURE__*/jsx(TrailingVisual, {}) : TrailingVisual
|
|
173
|
+
}), trailingAction]
|
|
174
|
+
}), characterLimit && /*#__PURE__*/jsxs(Fragment, {
|
|
175
|
+
children: [/*#__PURE__*/jsx(VisuallyHidden, {
|
|
176
|
+
"aria-live": "polite",
|
|
177
|
+
role: "status",
|
|
178
|
+
children: screenReaderMessage
|
|
179
|
+
}), /*#__PURE__*/jsxs(VisuallyHidden, {
|
|
180
|
+
id: characterCountStaticMessageId,
|
|
181
|
+
children: ["You can enter up to ", characterLimit, " ", characterLimit === 1 ? 'character' : 'characters']
|
|
182
|
+
}), /*#__PURE__*/jsxs(Text, {
|
|
183
|
+
"aria-hidden": "true",
|
|
184
|
+
id: characterCountId,
|
|
185
|
+
size: "small",
|
|
186
|
+
className: clsx(classes.CharacterCounter, isOverLimit && classes['CharacterCounter--error']),
|
|
187
|
+
children: [isOverLimit && /*#__PURE__*/jsx(AlertFillIcon, {
|
|
188
|
+
size: 16
|
|
189
|
+
}), characterCount]
|
|
190
|
+
})]
|
|
191
|
+
})]
|
|
118
192
|
});
|
|
119
193
|
});
|
|
120
194
|
TextInput.displayName = 'TextInput';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.prc-Textarea-TextArea-snlco{appearance:none;background-color:transparent;border:0;color:inherit;font-family:inherit;font-size:inherit;resize:both;width:100%}.prc-Textarea-TextArea-snlco:focus{outline:0}.prc-Textarea-TextArea-snlco[data-resize=none]{resize:none}.prc-Textarea-TextArea-snlco[data-resize=both]{resize:both}.prc-Textarea-TextArea-snlco[data-resize=horizontal]{resize:horizontal}.prc-Textarea-TextArea-snlco[data-resize=vertical]{resize:vertical}.prc-Textarea-TextArea-snlco:disabled{resize:none}
|
|
2
|
-
/*# sourceMappingURL=TextArea-
|
|
1
|
+
.prc-Textarea-TextArea-snlco{appearance:none;background-color:transparent;border:0;color:inherit;font-family:inherit;font-size:inherit;resize:both;width:100%}.prc-Textarea-TextArea-snlco:focus{outline:0}.prc-Textarea-TextArea-snlco[data-resize=none]{resize:none}.prc-Textarea-TextArea-snlco[data-resize=both]{resize:both}.prc-Textarea-TextArea-snlco[data-resize=horizontal]{resize:horizontal}.prc-Textarea-TextArea-snlco[data-resize=vertical]{resize:vertical}.prc-Textarea-TextArea-snlco:disabled{resize:none}.prc-Textarea-CharacterCounter-qnOXd{align-items:center;color:var(--fgColor-muted,var(--color-fg-muted));display:flex;gap:var(--control-xsmall-gap,.25rem)}.prc-Textarea-CharacterCounter--error-eewrs{color:var(--fgColor-danger,var(--color-danger-fg))}
|
|
2
|
+
/*# sourceMappingURL=TextArea-53e27580.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Textarea/TextArea.module.css.js"],"names":[],"mappings":"AAAA,6BAQE,eAAgB,CAFhB,4BAA6B,CAC7B,QAAS,CAHT,aAAc,CAFd,mBAAoB,CACpB,iBAAkB,CAElB,WAAY,CAJZ,UAQF,CAEA,mCACE,SACF,CAEA,+CACE,WACF,CAEA,+CACE,WACF,CAEA,qDACE,iBACF,CAEA,mDACE,eACF,CAEA,sCACE,WACF,CAEA,qCAEE,kBAAmB,CAEnB,gDAA2B,CAH3B,YAAa,CAEb,oCAEF,CAEA,4CACE,kDACF","file":"TextArea-53e27580.css","sourcesContent":[".TextArea {\n width: 100%;\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n resize: both;\n background-color: transparent;\n border: 0;\n appearance: none;\n}\n\n.TextArea:focus {\n outline: 0;\n}\n\n.TextArea[data-resize='none'] {\n resize: none;\n}\n\n.TextArea[data-resize='both'] {\n resize: both;\n}\n\n.TextArea[data-resize='horizontal'] {\n resize: horizontal;\n}\n\n.TextArea[data-resize='vertical'] {\n resize: vertical;\n}\n\n.TextArea:disabled {\n resize: none;\n}\n\n.CharacterCounter {\n display: flex;\n align-items: center;\n gap: var(--control-xsmall-gap);\n color: var(--fgColor-muted);\n}\n\n.CharacterCounter--error {\n color: var(--fgColor-danger);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import './TextArea-
|
|
1
|
+
import './TextArea-53e27580.css';
|
|
2
2
|
|
|
3
|
-
var classes = {"TextArea":"prc-Textarea-TextArea-snlco"};
|
|
3
|
+
var classes = {"TextArea":"prc-Textarea-TextArea-snlco","CharacterCounter":"prc-Textarea-CharacterCounter-qnOXd","CharacterCounter--error":"prc-Textarea-CharacterCounter--error-eewrs"};
|
|
4
4
|
|
|
5
5
|
export { classes as default };
|
|
@@ -42,6 +42,11 @@ export type TextareaProps = {
|
|
|
42
42
|
* CSS styles to apply to the Textarea
|
|
43
43
|
*/
|
|
44
44
|
style?: React.CSSProperties;
|
|
45
|
+
/**
|
|
46
|
+
* Optional character limit for the textarea. If provided, a character counter will be displayed below the textarea.
|
|
47
|
+
* When the limit is exceeded, validation styling will be applied.
|
|
48
|
+
*/
|
|
49
|
+
characterLimit?: number;
|
|
45
50
|
} & TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
46
51
|
/**
|
|
47
52
|
* An accessible, native textarea component that supports validation states.
|
|
@@ -84,6 +89,11 @@ declare const Textarea: React.ForwardRefExoticComponent<{
|
|
|
84
89
|
* CSS styles to apply to the Textarea
|
|
85
90
|
*/
|
|
86
91
|
style?: React.CSSProperties;
|
|
92
|
+
/**
|
|
93
|
+
* Optional character limit for the textarea. If provided, a character counter will be displayed below the textarea.
|
|
94
|
+
* When the limit is exceeded, validation styling will be applied.
|
|
95
|
+
*/
|
|
96
|
+
characterLimit?: number;
|
|
87
97
|
} & TextareaHTMLAttributes<HTMLTextAreaElement> & React.RefAttributes<HTMLTextAreaElement>>;
|
|
88
98
|
declare const _default: WithSlotMarker<typeof Textarea>;
|
|
89
99
|
export default _default;
|