@fpkit/acss 2.2.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/libs/chunk-5RAWNUVD.js +8 -0
  2. package/libs/chunk-5RAWNUVD.js.map +1 -0
  3. package/libs/{chunk-UJAQVHWC.js → chunk-CWRNJA4P.js} +2 -2
  4. package/libs/{chunk-R7NLLZU2.cjs → chunk-DYFAUAB7.cjs} +3 -3
  5. package/libs/chunk-NWJDAHP6.cjs +17 -0
  6. package/libs/chunk-NWJDAHP6.cjs.map +1 -0
  7. package/libs/components/breadcrumbs/breadcrumb.cjs +5 -5
  8. package/libs/components/breadcrumbs/breadcrumb.d.cts +2 -2
  9. package/libs/components/breadcrumbs/breadcrumb.d.ts +2 -2
  10. package/libs/components/breadcrumbs/breadcrumb.js +2 -2
  11. package/libs/components/flexbox/flex.css +1 -0
  12. package/libs/components/flexbox/flex.css.map +1 -0
  13. package/libs/components/flexbox/flex.min.css +3 -0
  14. package/libs/components/link/link.cjs +5 -5
  15. package/libs/components/link/link.css +1 -1
  16. package/libs/components/link/link.css.map +1 -1
  17. package/libs/components/link/link.d.cts +2 -131
  18. package/libs/components/link/link.d.ts +2 -131
  19. package/libs/components/link/link.js +1 -1
  20. package/libs/components/link/link.min.css +2 -2
  21. package/libs/components/nav/nav.css +1 -1
  22. package/libs/components/nav/nav.css.map +1 -1
  23. package/libs/components/nav/nav.min.css +2 -2
  24. package/libs/hooks.cjs +3 -3
  25. package/libs/hooks.d.cts +1 -1
  26. package/libs/hooks.d.ts +1 -1
  27. package/libs/hooks.js +2 -2
  28. package/libs/index.cjs +30 -29
  29. package/libs/index.cjs.map +1 -1
  30. package/libs/index.css +1 -1
  31. package/libs/index.css.map +1 -1
  32. package/libs/index.d.cts +246 -290
  33. package/libs/index.d.ts +246 -290
  34. package/libs/index.js +15 -15
  35. package/libs/index.js.map +1 -1
  36. package/libs/link-59ad884f.d.ts +371 -0
  37. package/package.json +2 -2
  38. package/src/components/flexbox/README.mdx +996 -0
  39. package/src/components/flexbox/flex.scss +847 -0
  40. package/src/components/flexbox/flex.stories.tsx +1233 -0
  41. package/src/components/flexbox/flex.test.tsx +689 -0
  42. package/src/components/flexbox/flex.tsx +484 -0
  43. package/src/components/flexbox/flex.types.ts +224 -0
  44. package/src/components/link/link.scss +4 -10
  45. package/src/components/link/link.tsx +18 -3
  46. package/src/components/nav/nav.scss +1 -1
  47. package/src/index.scss +1 -0
  48. package/src/index.ts +19 -2
  49. package/src/patterns/page/page-header.tsx +1 -3
  50. package/src/styles/flexbox/flex.css +736 -0
  51. package/src/styles/flexbox/flex.css.map +1 -0
  52. package/src/styles/index.css +739 -9
  53. package/src/styles/index.css.map +1 -1
  54. package/src/styles/link/link.css +2 -6
  55. package/src/styles/link/link.css.map +1 -1
  56. package/src/styles/nav/nav.css +3 -3
  57. package/libs/chunk-5PJYLVFY.cjs +0 -17
  58. package/libs/chunk-5PJYLVFY.cjs.map +0 -1
  59. package/libs/chunk-NNTBIHSD.js +0 -8
  60. package/libs/chunk-NNTBIHSD.js.map +0 -1
  61. package/libs/components/alert/alert.min.min.css +0 -2
  62. package/libs/components/badge/badge.min.min.css +0 -2
  63. package/libs/components/breadcrumbs/breadcrumb.min.min.css +0 -2
  64. package/libs/components/buttons/button.min.min.css +0 -2
  65. package/libs/components/cards/card-style.min.min.css +0 -2
  66. package/libs/components/cards/card.min.min.css +0 -2
  67. package/libs/components/details/details.min.min.css +0 -2
  68. package/libs/components/dialog/dialog.min.min.css +0 -2
  69. package/libs/components/form/form.min.min.css +0 -2
  70. package/libs/components/icons/icon.min.min.css +0 -2
  71. package/libs/components/images/img.min.min.css +0 -2
  72. package/libs/components/layout/landmarks.min.min.css +0 -2
  73. package/libs/components/link/link.min.min.css +0 -2
  74. package/libs/components/list/list.min.min.css +0 -2
  75. package/libs/components/nav/nav.min.min.css +0 -2
  76. package/libs/components/progress/progress.min.min.css +0 -2
  77. package/libs/components/styles/index.min.min.css +0 -2
  78. package/libs/components/tag/tag.min.min.css +0 -2
  79. package/libs/components/text-to-speech/text-to-speech.min.min.css +0 -2
  80. /package/libs/{chunk-UJAQVHWC.js.map → chunk-CWRNJA4P.js.map} +0 -0
  81. /package/libs/{chunk-R7NLLZU2.cjs.map → chunk-DYFAUAB7.cjs.map} +0 -0
@@ -0,0 +1,484 @@
1
+ import React from "react";
2
+ import UI from "../ui";
3
+ import type {
4
+ FlexProps,
5
+ FlexItemProps,
6
+ FlexSpacerProps,
7
+ FlexComponent,
8
+ ResponsiveFlexProps,
9
+ FlexContainerElement,
10
+ FlexItemElement,
11
+ } from "./flex.types";
12
+
13
+ /**
14
+ * Generates CSS class names from flex props
15
+ * Converts prop values to corresponding utility class names
16
+ *
17
+ * @param props - Flex properties to convert
18
+ * @param prefix - Optional breakpoint prefix (e.g., 'sm:', 'md:')
19
+ * @returns Array of CSS class names
20
+ */
21
+ const generateFlexClasses = (props: ResponsiveFlexProps, prefix = ""): string[] => {
22
+ const classes: string[] = [];
23
+
24
+ if (props.direction) {
25
+ const dirMap = {
26
+ row: "flex-row",
27
+ "row-reverse": "flex-row-reverse",
28
+ column: "flex-col",
29
+ "column-reverse": "flex-col-reverse",
30
+ };
31
+ classes.push(`${prefix}${dirMap[props.direction]}`);
32
+ }
33
+
34
+ if (props.wrap) {
35
+ const wrapMap = {
36
+ wrap: "flex-wrap",
37
+ nowrap: "flex-nowrap",
38
+ "wrap-reverse": "flex-wrap-reverse",
39
+ };
40
+ classes.push(`${prefix}${wrapMap[props.wrap]}`);
41
+ }
42
+
43
+ if (props.gap) {
44
+ classes.push(`${prefix}gap-${props.gap}`);
45
+ }
46
+
47
+ if (props.rowGap) {
48
+ classes.push(`${prefix}row-gap-${props.rowGap}`);
49
+ }
50
+
51
+ if (props.colGap) {
52
+ classes.push(`${prefix}col-gap-${props.colGap}`);
53
+ }
54
+
55
+ if (props.justify) {
56
+ const justifyMap = {
57
+ start: "justify-start",
58
+ end: "justify-end",
59
+ center: "justify-center",
60
+ between: "justify-between",
61
+ around: "justify-around",
62
+ evenly: "justify-evenly",
63
+ };
64
+ classes.push(`${prefix}${justifyMap[props.justify]}`);
65
+ }
66
+
67
+ if (props.align) {
68
+ const alignMap = {
69
+ start: "items-start",
70
+ end: "items-end",
71
+ center: "items-center",
72
+ baseline: "items-baseline",
73
+ stretch: "items-stretch",
74
+ };
75
+ classes.push(`${prefix}${alignMap[props.align]}`);
76
+ }
77
+
78
+ if (props.alignContent) {
79
+ const alignContentMap = {
80
+ start: "content-start",
81
+ end: "content-end",
82
+ center: "content-center",
83
+ between: "content-between",
84
+ around: "content-around",
85
+ evenly: "content-evenly",
86
+ stretch: "content-stretch",
87
+ };
88
+ classes.push(`${prefix}${alignContentMap[props.alignContent]}`);
89
+ }
90
+
91
+ return classes;
92
+ };
93
+
94
+ /**
95
+ * Flex - A flexible container component for creating flexbox layouts
96
+ *
97
+ * Provides a declarative React API for flexbox layouts with responsive props,
98
+ * preset variants, and full TypeScript support. Built on top of the fpkit
99
+ * flexbox utility system, converting props to utility classes for optimal performance.
100
+ *
101
+ * ## Features
102
+ * - **Compound Pattern**: Use Flex.Item and Flex.Spacer sub-components
103
+ * - **Responsive Props**: Different layouts at sm/md/lg/xl breakpoints
104
+ * - **Preset Variants**: Common patterns like 'center', 'between', 'stack'
105
+ * - **CSS Custom Properties**: Runtime theming via styles prop
106
+ * - **Polymorphic**: Render as semantic container elements via 'as' prop
107
+ * - **Type-Safe**: Full TypeScript support with autocomplete
108
+ *
109
+ * ## Semantic Elements Only
110
+ * The `as` prop is restricted to semantic container elements:
111
+ * - **Block containers**: div (default), section, article, aside, main, header, footer
112
+ * - **List containers**: ul, ol, dl, nav
113
+ * - **Form containers**: form, fieldset
114
+ *
115
+ * This restriction ensures proper HTML structure and prevents misuse as inline
116
+ * or interactive elements (e.g., span, a, button).
117
+ *
118
+ * ## Accessibility
119
+ * - Uses semantic HTML by default (div, but customizable via 'as' prop)
120
+ * - Forwards all ARIA attributes to the rendered element
121
+ * - No interactive behavior by default (purely layout)
122
+ *
123
+ * ## Breakpoints
124
+ * - **sm**: 30rem (480px)
125
+ * - **md**: 48rem (768px)
126
+ * - **lg**: 62rem (992px)
127
+ * - **xl**: 80rem (1280px)
128
+ *
129
+ * @example
130
+ * // Basic flex container
131
+ * <Flex direction="row" gap="md" justify="between" align="center">
132
+ * <div>Item 1</div>
133
+ * <div>Item 2</div>
134
+ * </Flex>
135
+ *
136
+ * @example
137
+ * // Responsive layout - column on mobile, row on medium+
138
+ * <Flex direction="column" md={{ direction: "row", gap: "lg" }}>
139
+ * <Flex.Item flex="1">Content 1</Flex.Item>
140
+ * <Flex.Item flex="1">Content 2</Flex.Item>
141
+ * </Flex>
142
+ *
143
+ * @example
144
+ * // Preset variant
145
+ * <Flex variant="center">
146
+ * <div>Centered content</div>
147
+ * </Flex>
148
+ *
149
+ * @example
150
+ * // Using Flex.Spacer to push items apart
151
+ * <Flex>
152
+ * <div>Left</div>
153
+ * <Flex.Spacer />
154
+ * <div>Right</div>
155
+ * </Flex>
156
+ *
157
+ * @example
158
+ * // Custom CSS properties
159
+ * <Flex styles={{ '--flex-gap': '2rem' }}>
160
+ * <div>Item</div>
161
+ * </Flex>
162
+ *
163
+ * @example
164
+ * // Semantic HTML with 'as' prop
165
+ * <Flex as="nav" role="navigation" aria-label="Main navigation">
166
+ * <a href="/">Home</a>
167
+ * <a href="/about">About</a>
168
+ * </Flex>
169
+ *
170
+ * @example
171
+ * // Semantic list structure
172
+ * <Flex as="ul" gap="md">
173
+ * <Flex.Item as="li">Item 1</Flex.Item>
174
+ * <Flex.Item as="li">Item 2</Flex.Item>
175
+ * </Flex>
176
+ */
177
+ const FlexBase = React.forwardRef<HTMLElement, FlexProps>((props, ref) => {
178
+ const {
179
+ variant,
180
+ inline = false,
181
+ as = "div",
182
+ className = "",
183
+ styles,
184
+ children,
185
+ sm,
186
+ md,
187
+ lg,
188
+ xl,
189
+ direction,
190
+ wrap,
191
+ gap,
192
+ rowGap,
193
+ colGap,
194
+ justify,
195
+ align,
196
+ alignContent,
197
+ ...rest
198
+ } = props;
199
+
200
+ const classes: string[] = [];
201
+
202
+ // Base flex class
203
+ classes.push(inline ? "flex-inline" : "flex");
204
+
205
+ // Apply variant preset if specified
206
+ if (variant) {
207
+ const variantMap = {
208
+ center: "flex-center",
209
+ between: "flex-between",
210
+ around: "flex-around",
211
+ stack: "flex-stack",
212
+ spread: "flex-spread",
213
+ };
214
+ classes.push(variantMap[variant]);
215
+ }
216
+
217
+ // Base responsive props
218
+ classes.push(
219
+ ...generateFlexClasses({
220
+ direction,
221
+ wrap,
222
+ gap,
223
+ rowGap,
224
+ colGap,
225
+ justify,
226
+ align,
227
+ alignContent,
228
+ })
229
+ );
230
+
231
+ // Responsive breakpoint classes
232
+ if (sm) {
233
+ classes.push(...generateFlexClasses(sm, "sm:"));
234
+ }
235
+ if (md) {
236
+ classes.push(...generateFlexClasses(md, "md:"));
237
+ }
238
+ if (lg) {
239
+ classes.push(...generateFlexClasses(lg, "lg:"));
240
+ }
241
+ if (xl) {
242
+ classes.push(...generateFlexClasses(xl, "xl:"));
243
+ }
244
+
245
+ // Merge custom className
246
+ const allClasses = [...classes, className].filter(Boolean).join(" ");
247
+
248
+ return (
249
+ <UI as={as} ref={ref} classes={allClasses} styles={styles} {...rest}>
250
+ {children}
251
+ </UI>
252
+ );
253
+ });
254
+
255
+ FlexBase.displayName = "Flex";
256
+
257
+ /**
258
+ * Flex.Item - Individual flex item component with sizing controls
259
+ *
260
+ * Provides fine-grained control over flex item behavior including grow,
261
+ * shrink, basis, alignment, and order. Supports responsive flex sizing
262
+ * at different breakpoints.
263
+ *
264
+ * ## Semantic Elements
265
+ * The `as` prop accepts container elements plus list item elements:
266
+ * - **Block containers**: div (default), section, article, aside, main, header, footer
267
+ * - **List containers**: ul, ol, dl, nav
268
+ * - **Form containers**: form, fieldset
269
+ * - **List items**: li, dt, dd
270
+ *
271
+ * List item elements (li, dt, dd) are included to support semantic list
272
+ * structures within flex containers.
273
+ *
274
+ * ## Props
275
+ * - **grow**: Flex grow factor (0 | 1)
276
+ * - **shrink**: Flex shrink factor (0 | 1)
277
+ * - **basis**: Flex basis ('auto' | '0' | 'full')
278
+ * - **flex**: Flex shorthand ('1' | 'auto' | 'initial' | 'none')
279
+ * - **alignSelf**: Override parent align-items
280
+ * - **order**: Visual order ('first' | 'last' | 'none')
281
+ *
282
+ * @example
283
+ * // Flex item that grows to fill available space
284
+ * <Flex.Item flex="1">
285
+ * Flexible content
286
+ * </Flex.Item>
287
+ *
288
+ * @example
289
+ * // Fixed-width item that doesn't grow or shrink
290
+ * <Flex.Item flex="none" styles={{ width: '200px' }}>
291
+ * Fixed width
292
+ * </Flex.Item>
293
+ *
294
+ * @example
295
+ * // Responsive flex - no grow on mobile, grow on medium+
296
+ * <Flex.Item flex="none" md={{ flex: "1" }}>
297
+ * Responsive item
298
+ * </Flex.Item>
299
+ *
300
+ * @example
301
+ * // Custom alignment for individual item
302
+ * <Flex.Item alignSelf="end">
303
+ * Aligned to end
304
+ * </Flex.Item>
305
+ *
306
+ * @example
307
+ * // Change visual order
308
+ * <Flex.Item order="last">
309
+ * Shows last visually
310
+ * </Flex.Item>
311
+ *
312
+ * @example
313
+ * // Semantic list item
314
+ * <Flex as="ul" gap="md">
315
+ * <Flex.Item as="li">List item 1</Flex.Item>
316
+ * <Flex.Item as="li">List item 2</Flex.Item>
317
+ * </Flex>
318
+ */
319
+ const FlexItem = React.forwardRef<HTMLElement, FlexItemProps>((props, ref) => {
320
+ const {
321
+ grow,
322
+ shrink,
323
+ basis,
324
+ flex,
325
+ alignSelf,
326
+ order,
327
+ as = "div",
328
+ className = "",
329
+ styles,
330
+ children,
331
+ sm,
332
+ md,
333
+ lg,
334
+ xl,
335
+ ...rest
336
+ } = props;
337
+
338
+ const classes: string[] = [];
339
+
340
+ // Apply flex sizing
341
+ if (flex) {
342
+ const flexMap = {
343
+ "1": "flex-1",
344
+ auto: "flex-auto",
345
+ initial: "flex-initial",
346
+ none: "flex-none",
347
+ };
348
+ classes.push(flexMap[flex]);
349
+ }
350
+
351
+ // Individual flex properties
352
+ if (grow !== undefined) {
353
+ classes.push(`flex-grow-${grow}`);
354
+ }
355
+ if (shrink !== undefined) {
356
+ classes.push(`flex-shrink-${shrink}`);
357
+ }
358
+ if (basis) {
359
+ const basisMap = {
360
+ auto: "flex-basis-auto",
361
+ "0": "flex-basis-0",
362
+ full: "flex-basis-full",
363
+ };
364
+ classes.push(basisMap[basis]);
365
+ }
366
+
367
+ // Align self
368
+ if (alignSelf) {
369
+ const alignSelfMap = {
370
+ auto: "self-auto",
371
+ start: "self-start",
372
+ end: "self-end",
373
+ center: "self-center",
374
+ baseline: "self-baseline",
375
+ stretch: "self-stretch",
376
+ };
377
+ classes.push(alignSelfMap[alignSelf]);
378
+ }
379
+
380
+ // Order
381
+ if (order) {
382
+ const orderMap = {
383
+ first: "order-first",
384
+ last: "order-last",
385
+ none: "order-none",
386
+ };
387
+ classes.push(orderMap[order]);
388
+ }
389
+
390
+ // Responsive flex sizing
391
+ if (sm?.flex) {
392
+ const flexMap = { "1": "flex-1", auto: "flex-auto", none: "flex-none" };
393
+ classes.push(`sm:${flexMap[sm.flex]}`);
394
+ }
395
+ if (md?.flex) {
396
+ const flexMap = { "1": "flex-1", auto: "flex-auto", none: "flex-none" };
397
+ classes.push(`md:${flexMap[md.flex]}`);
398
+ }
399
+ if (lg?.flex) {
400
+ const flexMap = { "1": "flex-1", auto: "flex-auto", none: "flex-none" };
401
+ classes.push(`lg:${flexMap[lg.flex]}`);
402
+ }
403
+ if (xl?.flex) {
404
+ const flexMap = { "1": "flex-1", auto: "flex-auto", none: "flex-none" };
405
+ classes.push(`xl:${flexMap[xl.flex]}`);
406
+ }
407
+
408
+ // Merge custom className
409
+ const allClasses = [...classes, className].filter(Boolean).join(" ");
410
+
411
+ return (
412
+ <UI as={as} ref={ref} classes={allClasses} styles={styles} {...rest}>
413
+ {children}
414
+ </UI>
415
+ );
416
+ });
417
+
418
+ FlexItem.displayName = "Flex.Item";
419
+
420
+ /**
421
+ * Flex.Spacer - Auto-expanding spacer element for pushing items apart
422
+ *
423
+ * Creates a flex item with `flex: 1 1 0%` that automatically expands
424
+ * to fill available space, pushing adjacent items to the edges.
425
+ * Commonly used to separate groups of items in a flex container.
426
+ *
427
+ * ## Semantic Elements Only
428
+ * The `as` prop is restricted to container elements:
429
+ * - **Block containers**: div (default), section, article, aside, main, header, footer
430
+ * - **List containers**: ul, ol, dl, nav
431
+ * - **Form containers**: form, fieldset
432
+ *
433
+ * Spacers are purely presentational and should typically use non-semantic
434
+ * containers like div.
435
+ *
436
+ * ## Accessibility
437
+ * - Renders as `<div>` by default (purely presentational)
438
+ * - Use `aria-hidden="true"` if purely decorative
439
+ * - Consider semantic alternatives for critical spacing
440
+ *
441
+ * @example
442
+ * // Push items to opposite edges
443
+ * <Flex>
444
+ * <div>Left side</div>
445
+ * <Flex.Spacer />
446
+ * <div>Right side</div>
447
+ * </Flex>
448
+ *
449
+ * @example
450
+ * // Multiple items with spacers
451
+ * <Flex>
452
+ * <div>Start</div>
453
+ * <Flex.Spacer />
454
+ * <div>Middle</div>
455
+ * <Flex.Spacer />
456
+ * <div>End</div>
457
+ * </Flex>
458
+ */
459
+ const FlexSpacer = React.forwardRef<HTMLElement, FlexSpacerProps>((props, ref) => {
460
+ const { as = "div", className = "", styles, ...rest } = props;
461
+
462
+ const classes = ["flex-1", className].filter(Boolean).join(" ");
463
+
464
+ return <UI as={as} ref={ref} classes={classes} styles={styles} {...rest} />;
465
+ });
466
+
467
+ FlexSpacer.displayName = "Flex.Spacer";
468
+
469
+ /**
470
+ * Attach sub-components to Flex using compound component pattern
471
+ */
472
+ const Flex = FlexBase as FlexComponent;
473
+ Flex.Item = FlexItem;
474
+ Flex.Spacer = FlexSpacer;
475
+
476
+ export default Flex;
477
+ export { FlexItem, FlexSpacer };
478
+ export type {
479
+ FlexProps,
480
+ FlexItemProps,
481
+ FlexSpacerProps,
482
+ FlexContainerElement,
483
+ FlexItemElement,
484
+ };
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Type definitions for Flex container components
3
+ * Supports responsive flexbox layouts with CSS custom properties
4
+ */
5
+
6
+ /**
7
+ * Valid HTML elements for Flex container
8
+ * Restricted to semantic container elements only
9
+ */
10
+ export type FlexContainerElement =
11
+ | "div"
12
+ | "section"
13
+ | "article"
14
+ | "aside"
15
+ | "main"
16
+ | "header"
17
+ | "footer"
18
+ | "nav"
19
+ | "ul"
20
+ | "ol"
21
+ | "dl"
22
+ | "form"
23
+ | "fieldset";
24
+
25
+ /**
26
+ * Valid HTML elements for Flex.Item
27
+ * Includes list item elements in addition to container elements
28
+ */
29
+ export type FlexItemElement = FlexContainerElement | "li" | "dt" | "dd";
30
+
31
+ /**
32
+ * Flex container direction
33
+ */
34
+ export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse";
35
+
36
+ /**
37
+ * Flex wrap behavior
38
+ */
39
+ export type FlexWrap = "wrap" | "nowrap" | "wrap-reverse";
40
+
41
+ /**
42
+ * Flex justify-content alignment
43
+ */
44
+ export type FlexJustify = "start" | "end" | "center" | "between" | "around" | "evenly";
45
+
46
+ /**
47
+ * Flex align-items alignment
48
+ */
49
+ export type FlexAlign = "start" | "end" | "center" | "baseline" | "stretch";
50
+
51
+ /**
52
+ * Flex align-content alignment (multi-line)
53
+ */
54
+ export type FlexAlignContent =
55
+ | "start"
56
+ | "end"
57
+ | "center"
58
+ | "between"
59
+ | "around"
60
+ | "evenly"
61
+ | "stretch";
62
+
63
+ /**
64
+ * Flex align-self alignment (individual items)
65
+ */
66
+ export type FlexAlignSelf = "auto" | "start" | "end" | "center" | "baseline" | "stretch";
67
+
68
+ /**
69
+ * Gap size options
70
+ */
71
+ export type FlexGap = "0" | "xs" | "sm" | "md" | "lg" | "xl";
72
+
73
+ /**
74
+ * Preset flex layout variants
75
+ */
76
+ export type FlexVariant = "center" | "between" | "around" | "stack" | "spread";
77
+
78
+ /**
79
+ * Responsive flex properties for breakpoints
80
+ */
81
+ export interface ResponsiveFlexProps {
82
+ /** Flex direction */
83
+ direction?: FlexDirection;
84
+ /** Flex wrap behavior */
85
+ wrap?: FlexWrap;
86
+ /** Gap between flex items */
87
+ gap?: FlexGap;
88
+ /** Row gap (vertical spacing) */
89
+ rowGap?: FlexGap;
90
+ /** Column gap (horizontal spacing) */
91
+ colGap?: FlexGap;
92
+ /** Justify content (main axis alignment) */
93
+ justify?: FlexJustify;
94
+ /** Align items (cross axis alignment) */
95
+ align?: FlexAlign;
96
+ /** Align content (multi-line alignment) */
97
+ alignContent?: FlexAlignContent;
98
+ }
99
+
100
+ /**
101
+ * Base Flex component props
102
+ *
103
+ * ## Semantic Elements Only
104
+ * The `as` prop is restricted to semantic container elements to ensure
105
+ * proper HTML structure and accessibility. Use only block-level container
106
+ * elements like div, section, article, or form elements.
107
+ *
108
+ * **Allowed elements**: div, section, article, aside, main, header, footer,
109
+ * nav, ul, ol, dl, form, fieldset
110
+ *
111
+ * **Not allowed**: span, a, button, input, or other inline/interactive elements
112
+ */
113
+ export interface FlexProps
114
+ extends ResponsiveFlexProps,
115
+ Omit<React.HTMLAttributes<HTMLElement>, "className"> {
116
+ /** Preset layout variant */
117
+ variant?: FlexVariant;
118
+ /** Use inline-flex instead of flex */
119
+ inline?: boolean;
120
+ /**
121
+ * Element type to render as
122
+ * @remarks Restricted to semantic container elements only for proper HTML structure
123
+ */
124
+ as?: FlexContainerElement;
125
+ /** Additional CSS class names */
126
+ className?: string;
127
+ /** Inline styles and CSS custom properties */
128
+ styles?: React.CSSProperties;
129
+ /** Children elements */
130
+ children?: React.ReactNode;
131
+ /** Responsive props for small screens (≥30rem / 480px) */
132
+ sm?: ResponsiveFlexProps;
133
+ /** Responsive props for medium screens (≥48rem / 768px) */
134
+ md?: ResponsiveFlexProps;
135
+ /** Responsive props for large screens (≥62rem / 992px) */
136
+ lg?: ResponsiveFlexProps;
137
+ /** Responsive props for extra large screens (≥80rem / 1280px) */
138
+ xl?: ResponsiveFlexProps;
139
+ }
140
+
141
+ /**
142
+ * Flex.Item component props
143
+ *
144
+ * ## Semantic Elements
145
+ * The `as` prop accepts container elements plus list item elements (li, dt, dd)
146
+ * to support semantic list structures within flex containers.
147
+ *
148
+ * **Allowed elements**: div, section, article, aside, main, header, footer,
149
+ * nav, ul, ol, dl, form, fieldset, li, dt, dd
150
+ */
151
+ export interface FlexItemProps extends Omit<React.HTMLAttributes<HTMLElement>, "className"> {
152
+ /** Flex grow factor */
153
+ grow?: 0 | 1;
154
+ /** Flex shrink factor */
155
+ shrink?: 0 | 1;
156
+ /** Flex basis */
157
+ basis?: "auto" | "0" | "full";
158
+ /** Flex shorthand: '1' | 'auto' | 'initial' | 'none' */
159
+ flex?: "1" | "auto" | "initial" | "none";
160
+ /** Align self (overrides parent align-items) */
161
+ alignSelf?: FlexAlignSelf;
162
+ /** Order of the flex item */
163
+ order?: "first" | "last" | "none";
164
+ /**
165
+ * Element type to render as
166
+ * @remarks Includes list item elements (li, dt, dd) in addition to container elements
167
+ */
168
+ as?: FlexItemElement;
169
+ /** Additional CSS class names */
170
+ className?: string;
171
+ /** Inline styles and CSS custom properties */
172
+ styles?: React.CSSProperties;
173
+ /** Children elements */
174
+ children?: React.ReactNode;
175
+ /** Responsive props for small screens (≥30rem / 480px) */
176
+ sm?: {
177
+ flex?: "1" | "auto" | "none";
178
+ };
179
+ /** Responsive props for medium screens (≥48rem / 768px) */
180
+ md?: {
181
+ flex?: "1" | "auto" | "none";
182
+ };
183
+ /** Responsive props for large screens (≥62rem / 992px) */
184
+ lg?: {
185
+ flex?: "1" | "auto" | "none";
186
+ };
187
+ /** Responsive props for extra large screens (≥80rem / 1280px) */
188
+ xl?: {
189
+ flex?: "1" | "auto" | "none";
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Flex.Spacer component props
195
+ * Creates an auto-expanding spacer element (flex: 1)
196
+ *
197
+ * ## Semantic Elements Only
198
+ * The `as` prop is restricted to container elements. Spacers are purely
199
+ * presentational and should use non-semantic containers like div.
200
+ *
201
+ * **Allowed elements**: div, section, article, aside, main, header, footer,
202
+ * nav, ul, ol, dl, form, fieldset
203
+ */
204
+ export interface FlexSpacerProps extends Omit<React.HTMLAttributes<HTMLElement>, "className"> {
205
+ /**
206
+ * Element type to render as
207
+ * @remarks Restricted to container elements. Default is 'div'.
208
+ */
209
+ as?: FlexContainerElement;
210
+ /** Additional CSS class names */
211
+ className?: string;
212
+ /** Inline styles and CSS custom properties */
213
+ styles?: React.CSSProperties;
214
+ }
215
+
216
+ /**
217
+ * Combined Flex component type with sub-components
218
+ */
219
+ export type FlexComponent = React.ForwardRefExoticComponent<
220
+ FlexProps & React.RefAttributes<HTMLElement>
221
+ > & {
222
+ Item: React.ForwardRefExoticComponent<FlexItemProps & React.RefAttributes<HTMLElement>>;
223
+ Spacer: React.ForwardRefExoticComponent<FlexSpacerProps & React.RefAttributes<HTMLElement>>;
224
+ };