@pushwoosh/kit-helpers 4.12.2 → 4.12.4

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.
@@ -1,838 +0,0 @@
1
-
2
-
3
- ---
4
- title: "@pushwoosh/kit-helpers — API Reference"
5
- version: "2.0.0"
6
- description: "React component library for building Pushwoosh products with TypeScript, styled-components, and comprehensive hook utilities"
7
- ---
8
-
9
- # @pushwoosh/kit-helpers
10
-
11
- **Version:** 2.0.0
12
-
13
- React component library for building Pushwoosh products with TypeScript, styled-components, and comprehensive hook utilities.
14
-
15
- > This page groups the API by Components, Hooks, Utilities, and Types. All styled-component props are prefixed with `$` to avoid DOM prop warnings.
16
-
17
- ---
18
-
19
- ## Components
20
-
21
- ### GridContainer
22
- - **Path:** `~/src/grid`
23
- - **Description:** Base grid container component using CSS Grid for flexible layouts
24
- - **Interface:**
25
- ```ts
26
- GridContainer<{
27
- $alignContent?: 'center' | 'start' | 'end' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch' | 'baseline';
28
- $alignItems?: 'center' | 'start' | 'end' | 'baseline' | 'stretch';
29
- $basis?: StrNum;
30
- $bgColor?: string;
31
- $border?: string | CssBoxSides<string>;
32
- $borderRadius?: StrNum;
33
- $bottom?: StrNum;
34
- $boxShadow?: string;
35
- $flex?: StrNum;
36
- $gap?: StrNum;
37
- $gridAutoFlow?: 'row' | 'column' | 'dense' | 'row dense' | 'column dense';
38
- $grow?: number;
39
- $height?: StrNum;
40
- $inset?: StrNum;
41
- $justifyContent?: 'center' | 'start' | 'end' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch';
42
- $justifyItems?: 'center' | 'start' | 'end' | 'baseline' | 'stretch';
43
- $left?: StrNum;
44
- $margin?: StrNum | CssBoxSides<StrNum>;
45
- $maxHeight?: StrNum;
46
- $maxWidth?: StrNum;
47
- $minHeight?: StrNum;
48
- $minWidth?: StrNum;
49
- $overflow?: 'hidden' | 'auto' | 'scroll' | 'visible';
50
- $overflowX?: 'hidden' | 'auto' | 'scroll' | 'visible';
51
- $overflowY?: 'hidden' | 'auto' | 'scroll' | 'visible';
52
- $padding?: StrNum | CssBoxSides<StrNum>;
53
- $placeItems?: 'center' | 'start' | 'end' | 'baseline' | 'stretch';
54
- $position?: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky';
55
- $right?: StrNum;
56
- $shrink?: number;
57
- $top?: StrNum;
58
- $width?: StrNum;
59
- $zIndex?: number;
60
- }>
61
- ```
62
-
63
- **Props**
64
-
65
- | Name | Type | Required | Default | Description | Values |
66
- |---|---|:---:|:---:|---|---|
67
- | `$alignContent` | enum | | | Aligns the grid content along the cross axis | `center`, `start`, `end`, `space-between`, `space-around`, `space-evenly`, `stretch`, `baseline` |
68
- | `$alignItems` | enum | | | Aligns grid items along the cross axis | `center`, `start`, `end`, `baseline`, `stretch` |
69
- | `$basis` | string\|number | | | `flex-basis` (only effective when parent is a flex container; number → px) | |
70
- | `$bgColor` | string | | | Background color of the grid container | |
71
- | `$border` | object | | | Border styling, can be string or object with top/right/bottom/left properties | |
72
- | `$borderRadius` | string\|number | | | Border radius, accepts number (converted to px) or string | |
73
- | `$bottom` | string\|number | | | `bottom` offset (number → px) | |
74
- | `$boxShadow` | string | | | CSS box shadow property | |
75
- | `$flex` | string\|number | | | `flex` shorthand (only effective when parent is a flex container) | |
76
- | `$gap` | string\|number | | | Gap between grid items, accepts number (converted to px) or string | |
77
- | `$gridAutoFlow` | enum | | | Controls how auto-placed items are inserted in the grid | `row`, `column`, `dense`, `row dense`, `column dense` |
78
- | `$grow` | number | | | `flex-grow` (only effective when parent is a flex container) | |
79
- | `$height` | string\|number | | | `height` (number → px; strings like `'100%'` / `'auto'` / `'fit-content'` pass through) | |
80
- | `$inset` | string\|number | | | `inset` CSS shorthand (number → px, string passes through, e.g. `'10px 20px'`) | |
81
- | `$justifyContent` | enum | | | Aligns the grid content along the main axis | `center`, `start`, `end`, `space-between`, `space-around`, `space-evenly`, `stretch` |
82
- | `$justifyItems` | enum | | | Aligns grid items along the main axis | `center`, `start`, `end`, `baseline`, `stretch` |
83
- | `$left` | string\|number | | | `left` offset (number → px) | |
84
- | `$margin` | object | | | Margin spacing, can be number/string or object with directional properties | |
85
- | `$maxHeight` | string\|number | | | `max-height` (number → px) | |
86
- | `$maxWidth` | string\|number | | | `max-width` (number → px) | |
87
- | `$minHeight` | string\|number | | | `min-height` (number → px) | |
88
- | `$minWidth` | string\|number | | | `min-width` (number → px) | |
89
- | `$overflow` | enum | | | `overflow` | `hidden`, `auto`, `scroll`, `visible` |
90
- | `$overflowX` | enum | | | `overflow-x` | `hidden`, `auto`, `scroll`, `visible` |
91
- | `$overflowY` | enum | | | `overflow-y` | `hidden`, `auto`, `scroll`, `visible` |
92
- | `$padding` | object | | | Padding spacing, can be number/string or object with directional properties | |
93
- | `$placeItems` | enum | | | Shorthand for align-items and justify-items | `center`, `start`, `end`, `baseline`, `stretch` |
94
- | `$position` | enum | | | `position` | `static`, `relative`, `absolute`, `fixed`, `sticky` |
95
- | `$right` | string\|number | | | `right` offset (number → px) | |
96
- | `$shrink` | number | | | `flex-shrink` (only effective when parent is a flex container) | |
97
- | `$top` | string\|number | | | `top` offset (number → px) | |
98
- | `$width` | string\|number | | | `width` (number → px; strings pass through) | |
99
- | `$zIndex` | number | | | `z-index` | |
100
-
101
- **Examples**
102
- ```tsx
103
- <GridContainer $gap={16} $padding={20} $bgColor="#f0f0f0">
104
- <div>Item 1</div>
105
- <div>Item 2</div>
106
- </GridContainer>
107
- ```
108
- ```tsx
109
- // Absolute tooltip
110
- <GridContainer $position="absolute" $top={40} $left={20} $width={350} $zIndex={10}>
111
- <Tooltip />
112
- </GridContainer>
113
- ```
114
- ```tsx
115
- // Stretch horizontally
116
- <GridContainer $position="absolute" $left={0} $right={0} $bottom={0}>
117
- <Footer />
118
- </GridContainer>
119
- ```
120
- ```tsx
121
- // Scrollable region
122
- <GridContainer $padding={16} $maxHeight={400} $overflow="auto">
123
- ...
124
- </GridContainer>
125
- ```
126
-
127
- **Notes**
128
- - All props are prefixed with `$` to indicate they are styled-component props
129
- - Numbers are automatically converted to `px` units; strings (e.g. `'100%'`, `'fit-content'`, `'2rem'`) pass through unchanged
130
- - Use `CssBoxSides` for asymmetric margin/padding/border
131
- - `$inset` maps directly to the CSS `inset` shorthand; for per-side control use individual `$top` / `$right` / `$bottom` / `$left`
132
- - Prefer specific layout components (Columns, Rows, Horizontal, Vertical) for common patterns
133
-
134
- ---
135
-
136
- ### Columns
137
- - **Path:** `~/src/grid`
138
- - **Description:** Grid container that creates equal or custom-sized columns
139
- - **Interface:** `Columns<{ $sizes: StrNum; ...GridContainerProps }>`
140
-
141
- **Props**
142
-
143
- | Name | Type | Required | Default | Description |
144
- |---|---|:---:|:---:|---|
145
- | `$sizes` | string\|number | ✓ | | Number for equal columns (e.g., `3`) or string for custom sizing (e.g., `"1fr 2fr"`) |
146
-
147
- **Examples**
148
- ```tsx
149
- <Columns $sizes={3} $gap={8}>
150
- <div>Col 1</div>
151
- <div>Col 2</div>
152
- <div>Col 3</div>
153
- </Columns>
154
- ```
155
- ```tsx
156
- <Columns $sizes="1fr 2fr" $gap={8}>
157
- <div>Narrow</div>
158
- <div>Wide</div>
159
- </Columns>
160
- ```
161
-
162
- **Notes**
163
- - Extends GridContainer with all its props
164
- - Number value creates equal columns using `repeat(n, 1fr)`
165
- - String value is passed directly to `grid-template-columns`
166
- - Ideal for responsive layouts with fixed column counts
167
-
168
- ---
169
-
170
- ### Rows
171
- - **Path:** `~/src/grid`
172
- - **Description:** Grid container that creates equal or custom-sized rows
173
- - **Interface:** `Rows<{ $sizes: StrNum; ...GridContainerProps }>`
174
-
175
- **Props**
176
-
177
- | Name | Type | Required | Default | Description |
178
- |---|---|:---:|:---:|---|
179
- | `$sizes` | string\|number | ✓ | | Number for equal rows or string for custom sizing |
180
-
181
- **Example**
182
- ```tsx
183
- <Rows $sizes={3} $gap={10}>
184
- <div>Row 1</div>
185
- <div>Row 2</div>
186
- <div>Row 3</div>
187
- </Rows>
188
- ```
189
-
190
- **Notes**
191
- - Similar to Columns but for vertical layouts
192
- - Extends GridContainer with all its props
193
- - Use for vertical stacking with specific row heights
194
-
195
- ---
196
-
197
- ### Horizontal
198
- - **Path:** `~/src/grid`
199
- - **Description:** Grid container with automatic column flow for horizontal layouts
200
- - **Interface:** `Horizontal<GridContainerProps>`
201
-
202
- **Example**
203
- ```tsx
204
- <Horizontal $justifyContent="start" $gap={8}>
205
- <Button>One</Button>
206
- <Button>Two</Button>
207
- <Button>Three</Button>
208
- </Horizontal>
209
- ```
210
-
211
- **Notes**
212
- - Pre-configured with `gridAutoFlow: 'column'`
213
- - Perfect for button groups, inline elements, or navigation items
214
- - Inherits all GridContainer props
215
- - Items flow horizontally automatically
216
-
217
- ---
218
-
219
- ### Vertical
220
- - **Path:** `~/src/grid`
221
- - **Description:** Grid container with automatic row flow for vertical layouts
222
- - **Interface:** `Vertical<GridContainerProps>`
223
-
224
- **Example**
225
- ```tsx
226
- <Vertical $gap={10}>
227
- <Header />
228
- <Content />
229
- <Footer />
230
- </Vertical>
231
- ```
232
-
233
- **Notes**
234
- - Pre-configured with `gridAutoFlow: 'row'`
235
- - Default behavior for vertical stacking
236
- - Inherits all GridContainer props
237
- - Use when you need explicit vertical flow control
238
-
239
- ---
240
-
241
- ### FlexContainer
242
- - **Path:** `~/src/flex`
243
- - **Description:** Base flex container component using CSS Flexbox for one-dimensional layouts
244
- - **Interface:**
245
- ```ts
246
- FlexContainer<{
247
- // Layout (flex-specific)
248
- $flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
249
- $flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
250
- // Container alignment (shared with GridContainer)
251
- $alignContent?: 'center' | 'start' | 'end' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch' | 'baseline';
252
- $alignItems?: 'center' | 'start' | 'end' | 'baseline' | 'stretch';
253
- $gap?: StrNum;
254
- $justifyContent?: 'center' | 'start' | 'end' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch';
255
- // Plus all CommonBoxProps: sizing ($width/$height/$min*/$max*), spacing ($padding/$margin),
256
- // appearance ($bgColor/$border/$borderRadius/$boxShadow), position ($position/$top/$right/$bottom/$left/$inset/$zIndex),
257
- // overflow ($overflow/$overflowX/$overflowY), flex-item ($flex/$grow/$shrink/$basis)
258
- }>
259
- ```
260
-
261
- **Props**
262
-
263
- | Name | Type | Required | Default | Description | Values |
264
- |---|---|:---:|:---:|---|---|
265
- | `$flexDirection` | enum | | `row` (browser default) | `flex-direction` — main axis direction | `row`, `row-reverse`, `column`, `column-reverse` |
266
- | `$flexWrap` | enum | | `nowrap` (browser default) | `flex-wrap` — whether items wrap onto multiple lines | `nowrap`, `wrap`, `wrap-reverse` |
267
-
268
- Plus everything from `CommonContainerProps` (`$alignContent`, `$alignItems`, `$justifyContent`, `$gap`) and `CommonBoxProps` — see `GridContainer` props table for the full shared list. Grid-specific props (`$gridAutoFlow`, `$justifyItems`, `$placeItems`) are NOT available on `FlexContainer`.
269
-
270
- **Examples**
271
- ```tsx
272
- <FlexContainer $gap={8} $alignItems="center">
273
- <Icon />
274
- <span>Label</span>
275
- </FlexContainer>
276
- ```
277
- ```tsx
278
- // Column with growing child filling remaining space
279
- <FlexContainer $flexDirection="column" $height="100vh">
280
- <Header />
281
- <Main $flex={1} $overflow="auto" />
282
- <Footer />
283
- </FlexContainer>
284
- ```
285
-
286
- **Notes**
287
- - Use when items have content-driven sizes or need to wrap; prefer `GridContainer` for explicit 2D tracks
288
- - Children can use `$flex` / `$grow` / `$shrink` / `$basis` from `CommonBoxProps` to control sizing — this works on any `GridContainer`/`FlexContainer` child too
289
- - Prefer the `Cluster` preset for wrap-based layouts (tags/chips)
290
-
291
- ---
292
-
293
- ### Cluster
294
- - **Path:** `~/src/flex`
295
- - **Description:** Flex container with wrapping enabled — for tag/chip/badge groups
296
- - **Interface:** `Cluster<FlexContainerProps>`
297
-
298
- **Example**
299
- ```tsx
300
- <Cluster $gap={8}>
301
- {tags.map((tag) => <Tag key={tag.id}>{tag.label}</Tag>)}
302
- </Cluster>
303
- ```
304
-
305
- **Notes**
306
- - Pre-configured with `$flexWrap: 'wrap'`
307
- - Inherits all `FlexContainer` props (override `$flexWrap` if needed)
308
- - Perfect for chip/tag rows that need to wrap on narrow widths
309
-
310
- ---
311
-
312
- ### Collapse
313
- - **Path:** `~/src/expand`
314
- - **Description:** Animated collapsible component with height transition
315
- - **Interface:** `Collapse<{ expanded: boolean; timeout?: number; className?: string; internalClassName?: string; children: (() => ReactNode) | ReactNode; }>`
316
-
317
- **Props**
318
-
319
- | Name | Type | Required | Default | Description |
320
- |---|---|:---:|:---:|---|
321
- | `expanded` | boolean | ✓ | | Controls whether content is visible or collapsed |
322
- | `timeout` | number | | `100` | Animation duration in milliseconds |
323
- | `className` | string | | | CSS class for the outer wrapper |
324
- | `internalClassName` | string | | | CSS class for the inner content wrapper |
325
- | `children` | function\|ReactNode | ✓ | | Content to show/hide, can be render function for lazy rendering |
326
-
327
- **Examples**
328
- ```tsx
329
- <Collapse expanded={isOpen}>
330
- <div>Collapsible content here</div>
331
- </Collapse>
332
- ```
333
- ```tsx
334
- <Collapse expanded={isOpen}>
335
- {() => <ExpensiveComponent />}
336
- </Collapse>
337
- ```
338
-
339
- **Notes**
340
- - Uses `react-transition-group` for animations
341
- - Height is calculated dynamically from content
342
- - Function children enable lazy rendering for performance
343
- - Smooth height and opacity transitions
344
- - Content is removed from DOM when collapsed
345
-
346
- ---
347
-
348
- ### ExpandTransition
349
- - **Path:** `~/src/expand`
350
- - **Description:** Advanced expand/collapse transition with zoom effect
351
- - **Interface:** `ExpandTransition<{ timeout?: number; className?: string; externalClassName?: string; internalClassName?: string; }>`
352
-
353
- **Props**
354
-
355
- | Name | Type | Required | Default | Description |
356
- |---|---|:---:|:---:|---|
357
- | `timeout` | number | | `100` | Animation duration in milliseconds |
358
- | `className` | string | | | Base CSS class for transition states |
359
- | `externalClassName` | string | | | Additional class for outer wrapper |
360
- | `internalClassName` | string | | | Class for inner content wrapper |
361
-
362
- **Example**
363
- ```tsx
364
- <TransitionGroup component={null}>
365
- {visible && (
366
- <ExpandTransition key={0}>
367
- <Card>Content</Card>
368
- </ExpandTransition>
369
- )}
370
- </TransitionGroup>
371
- ```
372
-
373
- **Notes**
374
- - Must be used with `TransitionGroup` from `react-transition-group`
375
- - Creates zoom-in/zoom-out effect with position animation
376
- - More complex than Collapse, use for special UI effects
377
- - Requires `key` prop when used in TransitionGroup
378
-
379
- ---
380
-
381
- ## Hooks
382
-
383
- ### useClickAway
384
- - **Path:** `~/src/hooks/useClickAway`
385
- - **Description:** Detects clicks outside a referenced element and triggers a callback
386
- - **Signature:**
387
- ```ts
388
- useClickAway<T extends HTMLElement>(
389
- use: boolean,
390
- ref: RefObject<T | null>,
391
- cb: (event: MouseEvent | TouchEvent) => void
392
- ): void
393
- ```
394
-
395
- **Params:** `use` – enable/disable; `ref` – target element ref; `cb` – callback on outside click
396
-
397
- **Returns:** `void`
398
-
399
- **Example**
400
- ```tsx
401
- const ref = useRef<HTMLDivElement>(null);
402
- useClickAway(isOpen, ref, () => setIsOpen(false));
403
- ```
404
-
405
- **Notes**
406
- - Handles both mouse and touch events
407
- - Callback is persisted to avoid re-subscriptions
408
- - Can be toggled on/off with `use` parameter
409
- - Perfect for dropdowns, modals, and popovers
410
- - Automatically cleans up event listeners
411
-
412
- ---
413
-
414
- ### usePersistentFunction
415
- - **Path:** `~/src/hooks/usePersistentFunction`
416
- - **Description:** Creates a stable function reference that always calls the latest version of a callback
417
- - **Signature:**
418
- ```ts
419
- usePersistentFunction<Args extends any[], Return>(
420
- callback: (...args: Args) => Return
421
- ): (...args: Args) => Return
422
- ```
423
-
424
- **Example**
425
- ```tsx
426
- const stableHandler = usePersistentFunction(() => {
427
- console.log(currentState); // Always uses latest state
428
- });
429
- ```
430
-
431
- **Notes**
432
- - Prevents unnecessary re-renders in child components
433
- - Always executes the latest callback version
434
- - Alternative to `useCallback` with empty deps
435
- - Ideal for event handlers and effect cleanup functions
436
- - Maintains referential equality across renders
437
-
438
- ---
439
-
440
- ### useAsync
441
- - **Path:** `~/src/hooks/useAsync`
442
- - **Description:** Automatically executes an async function and manages its state
443
- - **Signature:**
444
- ```ts
445
- useAsync<T extends FunctionReturningPromise>(fn: T, deps?: DependencyList): AsyncState<T>
446
- ```
447
-
448
- **Example**
449
- ```tsx
450
- const { loading, error, value } = useAsync(
451
- () => fetchUserData(userId),
452
- [userId]
453
- );
454
- ```
455
-
456
- **Notes**
457
- - Executes immediately on mount and when deps change
458
- - Handles loading states automatically
459
- - Catches and exposes errors
460
- - Starts with `loading: true`
461
- - Re-runs when dependencies change
462
-
463
- ---
464
-
465
- ### useAsyncFn
466
- - **Path:** `~/src/hooks/useAsyncFn`
467
- - **Description:** Returns an async function wrapper with state management
468
- - **Signature:**
469
- ```ts
470
- useAsyncFn<T extends FunctionReturningPromise>(
471
- fn: T,
472
- deps?: DependencyList,
473
- initialState?: AsyncState<T>
474
- ): [AsyncState<T>, (p?: CallbackParams) => ReturnType<T>]
475
- ```
476
-
477
- **Example**
478
- ```tsx
479
- const [state, doFetch] = useAsyncFn(
480
- () => api.saveData(data),
481
- [data]
482
- );
483
- // Later: doFetch({ reset: true });
484
- ```
485
-
486
- **Notes**
487
- - Manual trigger unlike `useAsync`
488
- - Returns both state and executable function
489
- - Supports `reset` option to clear previous state
490
- - Prevents race conditions with call tracking
491
- - Safe to use with unmounted components
492
-
493
- ---
494
-
495
- ### useAsyncFunction
496
- - **Path:** `~/src/hooks/useAsyncFunction`
497
- - **Description:** Creates a persistent async function with state tracking and call counting
498
- - **Signature:**
499
- ```ts
500
- useAsyncFunction<T extends FunctionReturningPromise>(fn: T): [AsyncFunctionState<T>, T]
501
- ```
502
-
503
- **Example**
504
- ```tsx
505
- const [state, saveUser] = useAsyncFunction(async (user) => {
506
- return api.saveUser(user);
507
- });
508
- // state.count tracks number of calls
509
- ```
510
-
511
- **Notes**
512
- - Includes call counter in state
513
- - Function reference is always stable
514
- - Tracks loading state per call
515
- - Useful for forms and repeated actions
516
- - Prevents state updates on unmounted components
517
-
518
- ---
519
-
520
- ### useEffectOnce
521
- - **Path:** `~/src/hooks/useEffectOnce`
522
- - **Description:** Runs an effect only once on mount
523
- - **Signature:** `useEffectOnce(effect: EffectCallback): void`
524
-
525
- **Example**
526
- ```tsx
527
- useEffectOnce(() => {
528
- initializeApp();
529
- return () => cleanup();
530
- });
531
- ```
532
-
533
- **Notes**
534
- - Equivalent to `useEffect` with empty deps
535
- - Cleaner API for one-time setup
536
- - Supports cleanup function return
537
- - Use for initialization logic
538
-
539
- ---
540
-
541
- ### useMount
542
- - **Path:** `~/src/hooks/useMount`
543
- - **Description:** Runs a function on component mount
544
- - **Signature:** `useMount(fn: () => void): void`
545
-
546
- **Example**
547
- ```tsx
548
- useMount(() => {
549
- console.log('Component mounted');
550
- });
551
- ```
552
-
553
- **Notes**
554
- - Simpler than `useEffectOnce` when no cleanup needed
555
- - Only for side effects on mount
556
- - No return value expected
557
-
558
- ---
559
-
560
- ### useUnmount
561
- - **Path:** `~/src/hooks/useUnmount`
562
- - **Description:** Runs a function on component unmount
563
- - **Signature:** `useUnmount(fn: () => any): void`
564
-
565
- **Example**
566
- ```tsx
567
- useUnmount(() => {
568
- saveProgress();
569
- disconnectSocket();
570
- });
571
- ```
572
-
573
- **Notes**
574
- - Always uses latest version of cleanup function
575
- - Perfect for cleanup operations
576
- - Saves form data, closes connections, etc.
577
- - Function ref is updated each render
578
-
579
- ---
580
-
581
- ### useMountedState
582
- - **Path:** `~/src/hooks/useMountedState`
583
- - **Description:** Returns a function that checks if component is still mounted
584
- - **Signature:** `useMountedState(): () => boolean`
585
-
586
- **Example**
587
- ```tsx
588
- const isMounted = useMountedState();
589
-
590
- setTimeout(() => {
591
- if (isMounted()) {
592
- setState(newValue);
593
- }
594
- }, 1000);
595
- ```
596
-
597
- **Notes**
598
- - Prevents state updates on unmounted components
599
- - Essential for async operations
600
- - Check before `setState` in callbacks
601
- - Stable function reference
602
-
603
- ---
604
-
605
- ### useDelayedValue
606
- - **Path:** `~/src/hooks/useDelayedValue`
607
- - **Description:** Delays value updates by specified milliseconds
608
- - **Signature:** `useDelayedValue<T>(value: T, delay: number): T`
609
-
610
- **Example**
611
- ```tsx
612
- const debouncedSearch = useDelayedValue(searchTerm, 300);
613
- useEffect(() => {
614
- performSearch(debouncedSearch);
615
- }, [debouncedSearch]);
616
- ```
617
-
618
- **Notes**
619
- - Acts as a debounce for value changes
620
- - Useful for search inputs and API calls
621
- - Cancels pending updates on new values
622
- - Returns initial value immediately
623
-
624
- ---
625
-
626
- ### useDelayedEffect
627
- - **Path:** `~/src/hooks/useDelayedEffect`
628
- - **Description:** Runs an effect after a delay with cancellation support
629
- - **Signature:**
630
- ```ts
631
- useDelayedEffect(
632
- effect: (getIsRunning: () => boolean) => void,
633
- deps: DependencyList,
634
- delay: number
635
- ): void
636
- ```
637
-
638
- **Example**
639
- ```tsx
640
- useDelayedEffect(
641
- (getIsRunning) => {
642
- if (getIsRunning()) {
643
- performExpensiveOperation();
644
- }
645
- },
646
- [data],
647
- 500
648
- );
649
- ```
650
-
651
- **Notes**
652
- - Provides cancellation check via `getIsRunning`
653
- - Clears timeout on deps change or unmount
654
- - Useful for debounced side effects
655
- - Check `getIsRunning()` before state updates
656
-
657
- ---
658
-
659
- ## Utilities
660
-
661
- ### formatNumber
662
- - **Path:** `~/src/formatNumber`
663
- - **Description:** Formats numbers with spacing or short notation
664
- - **Signature:** `formatNumber(number: number, format: 'spaced' | 'short'): string`
665
-
666
- **Examples**
667
- ```ts
668
- formatNumber(1234567, 'spaced') // '1 234 567'
669
- formatNumber(1234567, 'short') // '1.2M'
670
- formatNumber(999, 'short') // '999'
671
- ```
672
-
673
- **Notes**
674
- - `spaced`: Adds spaces every 3 digits
675
- - `short`: Uses K, M, B notation above 10,000
676
- - Short format keeps one decimal place
677
- - Numbers below 10K in short format use spaced display
678
- - Ideal for statistics and dashboards
679
-
680
- ---
681
-
682
- ### toCssValue
683
- - **Path:** `~/src/styled-helpers` (also re-exported from `~/src/grid` for back-compat)
684
- - **Description:** Converts number to px string or returns string as-is
685
- - **Signature:** `toCssValue(value: string | number): string`
686
-
687
- **Examples**
688
- ```ts
689
- toCssValue(16) // '16px'
690
- toCssValue('2rem') // '2rem'
691
- ```
692
-
693
- **Notes**
694
- - Used internally by grid and flex components
695
- - Numbers become pixels
696
- - Strings pass through unchanged
697
- - Enables flexible prop values
698
-
699
- ---
700
-
701
- ### elementAddListeners
702
- - **Path:** `~/src/hooks/useClickAway`
703
- - **Description:** Adds event listeners to elements with cleanup function
704
- - **Signature:**
705
- ```ts
706
- elementAddListeners<
707
- K extends keyof HTMLElementEventMap,
708
- E extends HTMLElement
709
- >(element: E | Document, eventNames: K | K[], listener: EventListener): () => void
710
- ```
711
-
712
- **Example**
713
- ```ts
714
- const cleanup = elementAddListeners(
715
- document,
716
- ['mousedown', 'touchstart'],
717
- handleClick
718
- );
719
- ```
720
-
721
- **Notes**
722
- - Returns cleanup function
723
- - Supports multiple event types
724
- - Works with `Document` or `HTMLElement`
725
- - Used internally by `useClickAway`
726
-
727
- ---
728
-
729
- ### subscribeClickAway
730
- - **Path:** `~/src/hooks/useClickAway`
731
- - **Description:** Subscribes to clicks outside an element
732
- - **Signature:**
733
- ```typescript
734
- subscribeClickAway<T extends HTMLElement>(
735
- element: T,
736
- callback: (event: MouseEvent | TouchEvent) => void
737
- ): () => void
738
- ```
739
-
740
- **Example**
741
- ```ts
742
- const unsubscribe = subscribeClickAway(dropdownEl, () => closeDropdown());
743
- ```
744
-
745
- **Notes**
746
- - Standalone version of `useClickAway` logic
747
- - Returns unsubscribe function
748
- - Handles mouse and touch events
749
- - Can be used outside React components
750
-
751
- ---
752
-
753
- ## Types
754
-
755
- ### StrNum
756
- - **Definition:** `type StrNum = string | number`
757
- - **Description:** Union type for CSS values that can be string or number
758
-
759
- ### CssBoxSides
760
- - **Definition:**
761
- ```ts
762
- type CssBoxSides<T> =
763
- | { top?: T; right?: T; bottom?: T; left?: T }
764
- | { horizontal: T; top?: T; bottom?: T }
765
- | { vertical: T; right?: T; left?: T }
766
- ```
767
- - **Description:** Flexible type for directional CSS properties like margin/padding
768
-
769
- ### CommonBoxProps
770
- - **Path:** `~/src/styled-helpers`
771
- - **Description:** Shared box-model/positioning/flex-item props consumed by both `GridContainer` and `FlexContainer`. Covers sizing (`$width`, `$height`, `$minWidth`/`$minHeight`, `$maxWidth`/`$maxHeight`), spacing (`$padding`, `$margin`), appearance (`$bgColor`, `$border`, `$borderRadius`, `$boxShadow`), position (`$position`, `$top`/`$right`/`$bottom`/`$left`, `$inset`, `$zIndex`), overflow (`$overflow`/`$overflowX`/`$overflowY`), and flex-item sizing (`$flex`, `$grow`, `$shrink`, `$basis`)
772
-
773
- ### CommonContainerProps
774
- - **Path:** `~/src/styled-helpers`
775
- - **Definition:** `CommonBoxProps & { $alignContent?: AlignContentValue; $alignItems?: ItemAlignmentValue; $gap?: StrNum; $justifyContent?: JustifyContentValue }`
776
- - **Description:** Extends `CommonBoxProps` with alignment props that work in both grid and flex contexts. Used as the base for `GridContainer` and `FlexContainer` props
777
-
778
- ### ItemAlignmentValue
779
- - **Path:** `~/src/styled-helpers`
780
- - **Definition:** `'center' | 'start' | 'end' | 'baseline' | 'stretch'`
781
- - **Description:** Valid values for item-level alignment props: `$alignItems`, `$justifyItems`, `$placeItems`
782
-
783
- ### JustifyContentValue
784
- - **Path:** `~/src/styled-helpers`
785
- - **Definition:** `'center' | 'start' | 'end' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch'`
786
- - **Description:** Valid values for `$justifyContent`. Per CSS Box Alignment L3, `justify-content` does NOT accept `baseline` — use `AlignContentValue` for `$alignContent`
787
-
788
- ### AlignContentValue
789
- - **Path:** `~/src/styled-helpers`
790
- - **Definition:** `JustifyContentValue | 'baseline'`
791
- - **Description:** Valid values for `$alignContent`. Same as `JustifyContentValue` plus `baseline` (which is spec-valid only for the cross-axis content distribution)
792
-
793
- ### AsyncState
794
- - **Definition:** `type AsyncState<T> = { loading: boolean; error?: Error; value?: T }`
795
- - **Description:** State shape for async operations with loading, error, and value
796
-
797
- ### FunctionReturningPromise
798
- - **Definition:** `type FunctionReturningPromise = (...args: any[]) => Promise<any>`
799
- - **Description:** Generic type for any async function
800
-
801
- ### PromiseType
802
- - **Definition:** `type PromiseType<P extends Promise<any>> = P extends Promise<infer T> ? T : never`
803
- - **Description:** Extracts the resolved type from a Promise
804
-
805
- ---
806
-
807
- ## Patterns
808
-
809
- ### styledComponentProps
810
- - **Description:** All styled-component props are prefixed with `$` to avoid React prop warnings
811
- - **Example:** `$gap, $padding, $margin` instead of `gap, padding, margin`
812
-
813
- ### lazyRendering
814
- - **Description:** Components accept function children for deferred rendering
815
- - **Example:** `<Collapse expanded={show}>{() => <ExpensiveComponent />}</Collapse>`
816
-
817
- ### persistentCallbacks
818
- - **Description:** Use `usePersistentFunction` to maintain stable references while using latest closure values
819
- - **Example:** `const stable = usePersistentFunction(callback)`
820
-
821
- ### asyncStateManagement
822
- - **Description:** Consistent async state shape with loading, error, and value properties
823
- - **Example:** All async hooks return `{ loading, error, value }` state
824
-
825
- ---
826
-
827
- ## Best Practices
828
- - Use specific layout components (Columns, Horizontal, Vertical) over generic GridContainer
829
- - Use the `Cluster` preset for wrap-based layouts; reach for `FlexContainer` for everything else
830
- - Prefer `FlexContainer` over `GridContainer` when item sizes are content-driven or you need wrapping; prefer Grid when you have explicit row/column tracks
831
- - Set `$flex` / `$grow` / `$shrink` / `$basis` on any `GridContainer`/`FlexContainer` child to control its size inside a flex parent — no extra wrapper needed
832
- - Prefix all styled-component props with `$` to avoid DOM prop warnings
833
- - Use `usePersistentFunction` for callbacks passed to memoized components
834
- - Check `isMounted()` before state updates in async operations
835
- - Use function children in `Collapse` for expensive components
836
- - Leverage TypeScript's discriminated unions in `AsyncState` for type safety
837
- - Use `useDelayedValue` for debouncing user input
838
- - Combine `useClickAway` with portals for robust dropdown behavior