@jiwambe/components 0.2.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 (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +367 -0
  3. package/dist/client.d.ts +40 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +46 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/components/Accordion/Accordion.d.ts +74 -0
  8. package/dist/components/Accordion/Accordion.d.ts.map +1 -0
  9. package/dist/components/Accordion/Accordion.js +297 -0
  10. package/dist/components/Accordion/Accordion.js.map +1 -0
  11. package/dist/components/Box/Box.d.ts +56 -0
  12. package/dist/components/Box/Box.d.ts.map +1 -0
  13. package/dist/components/Box/Box.js +51 -0
  14. package/dist/components/Box/Box.js.map +1 -0
  15. package/dist/components/Breadcrumb/Breadcrumb.d.ts +66 -0
  16. package/dist/components/Breadcrumb/Breadcrumb.d.ts.map +1 -0
  17. package/dist/components/Button/Button.d.ts +54 -0
  18. package/dist/components/Button/Button.d.ts.map +1 -0
  19. package/dist/components/Button/Button.js +92 -0
  20. package/dist/components/Button/Button.js.map +1 -0
  21. package/dist/components/Card/Card.d.ts +54 -0
  22. package/dist/components/Card/Card.d.ts.map +1 -0
  23. package/dist/components/Card/Card.js +98 -0
  24. package/dist/components/Card/Card.js.map +1 -0
  25. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +61 -0
  26. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -0
  27. package/dist/components/CheckboxGroup/CheckboxGroup.js +205 -0
  28. package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -0
  29. package/dist/components/Container/Container.d.ts +72 -0
  30. package/dist/components/Container/Container.d.ts.map +1 -0
  31. package/dist/components/Container/Container.js +69 -0
  32. package/dist/components/Container/Container.js.map +1 -0
  33. package/dist/components/DateInput/DateInput.d.ts +61 -0
  34. package/dist/components/DateInput/DateInput.d.ts.map +1 -0
  35. package/dist/components/DateInput/DateInput.js +234 -0
  36. package/dist/components/DateInput/DateInput.js.map +1 -0
  37. package/dist/components/Divider/Divider.d.ts +44 -0
  38. package/dist/components/Divider/Divider.d.ts.map +1 -0
  39. package/dist/components/Divider/Divider.js +35 -0
  40. package/dist/components/Divider/Divider.js.map +1 -0
  41. package/dist/components/Drawer/Drawer.d.ts +35 -0
  42. package/dist/components/Drawer/Drawer.d.ts.map +1 -0
  43. package/dist/components/Drawer/Drawer.js +37 -0
  44. package/dist/components/Drawer/Drawer.js.map +1 -0
  45. package/dist/components/FAQ/FAQ.d.ts +40 -0
  46. package/dist/components/FAQ/FAQ.d.ts.map +1 -0
  47. package/dist/components/FAQ/FAQ.js +161 -0
  48. package/dist/components/FAQ/FAQ.js.map +1 -0
  49. package/dist/components/Grid/Grid.d.ts +61 -0
  50. package/dist/components/Grid/Grid.d.ts.map +1 -0
  51. package/dist/components/Grid/Grid.js +95 -0
  52. package/dist/components/Grid/Grid.js.map +1 -0
  53. package/dist/components/Icon/Icon.d.ts +21 -0
  54. package/dist/components/Icon/Icon.d.ts.map +1 -0
  55. package/dist/components/Icon/Icon.js +167 -0
  56. package/dist/components/Icon/Icon.js.map +1 -0
  57. package/dist/components/Link/Link.d.ts +49 -0
  58. package/dist/components/Link/Link.d.ts.map +1 -0
  59. package/dist/components/Link/Link.js +70 -0
  60. package/dist/components/Link/Link.js.map +1 -0
  61. package/dist/components/List/List.d.ts +36 -0
  62. package/dist/components/List/List.d.ts.map +1 -0
  63. package/dist/components/List/List.js +42 -0
  64. package/dist/components/List/List.js.map +1 -0
  65. package/dist/components/List/index.d.ts +3 -0
  66. package/dist/components/List/index.d.ts.map +1 -0
  67. package/dist/components/Overlay/Overlay.d.ts +35 -0
  68. package/dist/components/Overlay/Overlay.d.ts.map +1 -0
  69. package/dist/components/Overlay/Overlay.js +51 -0
  70. package/dist/components/Overlay/Overlay.js.map +1 -0
  71. package/dist/components/PhoneInput/PhoneInput.d.ts +55 -0
  72. package/dist/components/PhoneInput/PhoneInput.d.ts.map +1 -0
  73. package/dist/components/PhoneInput/PhoneInput.js +255 -0
  74. package/dist/components/PhoneInput/PhoneInput.js.map +1 -0
  75. package/dist/components/Popover/Popover.d.ts +46 -0
  76. package/dist/components/Popover/Popover.d.ts.map +1 -0
  77. package/dist/components/Popover/Popover.js +57 -0
  78. package/dist/components/Popover/Popover.js.map +1 -0
  79. package/dist/components/ProductImage/ProductImage.d.ts +78 -0
  80. package/dist/components/ProductImage/ProductImage.d.ts.map +1 -0
  81. package/dist/components/ProductImage/ProductImage.js +220 -0
  82. package/dist/components/ProductImage/ProductImage.js.map +1 -0
  83. package/dist/components/RadioGroup/RadioGroup.d.ts +63 -0
  84. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -0
  85. package/dist/components/RadioGroup/RadioGroup.js +233 -0
  86. package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
  87. package/dist/components/Section/Section.d.ts +44 -0
  88. package/dist/components/Section/Section.d.ts.map +1 -0
  89. package/dist/components/Section/Section.js +48 -0
  90. package/dist/components/Section/Section.js.map +1 -0
  91. package/dist/components/Select/Select.d.ts +47 -0
  92. package/dist/components/Select/Select.d.ts.map +1 -0
  93. package/dist/components/Select/Select.js +153 -0
  94. package/dist/components/Select/Select.js.map +1 -0
  95. package/dist/components/SelectTab/SelectTab.d.ts +62 -0
  96. package/dist/components/SelectTab/SelectTab.d.ts.map +1 -0
  97. package/dist/components/SelectTab/SelectTab.js +192 -0
  98. package/dist/components/SelectTab/SelectTab.js.map +1 -0
  99. package/dist/components/Skeleton/Skeleton.d.ts +87 -0
  100. package/dist/components/Skeleton/Skeleton.d.ts.map +1 -0
  101. package/dist/components/Skeleton/Skeleton.js +97 -0
  102. package/dist/components/Skeleton/Skeleton.js.map +1 -0
  103. package/dist/components/Skeleton/index.d.ts +3 -0
  104. package/dist/components/Skeleton/index.d.ts.map +1 -0
  105. package/dist/components/Slider/Slider.d.ts +47 -0
  106. package/dist/components/Slider/Slider.d.ts.map +1 -0
  107. package/dist/components/Slider/Slider.js +147 -0
  108. package/dist/components/Slider/Slider.js.map +1 -0
  109. package/dist/components/Stack/Stack.d.ts +145 -0
  110. package/dist/components/Stack/Stack.d.ts.map +1 -0
  111. package/dist/components/Stack/Stack.js +80 -0
  112. package/dist/components/Stack/Stack.js.map +1 -0
  113. package/dist/components/Tab/Tab.d.ts +38 -0
  114. package/dist/components/Tab/Tab.d.ts.map +1 -0
  115. package/dist/components/Tab/Tab.js +146 -0
  116. package/dist/components/Tab/Tab.js.map +1 -0
  117. package/dist/components/TextArea/TextArea.d.ts +32 -0
  118. package/dist/components/TextArea/TextArea.d.ts.map +1 -0
  119. package/dist/components/TextArea/TextArea.js +118 -0
  120. package/dist/components/TextArea/TextArea.js.map +1 -0
  121. package/dist/components/TextInput/TextInput.d.ts +35 -0
  122. package/dist/components/TextInput/TextInput.d.ts.map +1 -0
  123. package/dist/components/TextInput/TextInput.js +128 -0
  124. package/dist/components/TextInput/TextInput.js.map +1 -0
  125. package/dist/components/Toggle/Toggle.d.ts +83 -0
  126. package/dist/components/Toggle/Toggle.d.ts.map +1 -0
  127. package/dist/components/Toggle/Toggle.js +121 -0
  128. package/dist/components/Toggle/Toggle.js.map +1 -0
  129. package/dist/components/Typography/Typography.d.ts +321 -0
  130. package/dist/components/Typography/Typography.d.ts.map +1 -0
  131. package/dist/components/Typography/Typography.js +21 -0
  132. package/dist/components/Typography/Typography.js.map +1 -0
  133. package/dist/components/UploadInput/UploadInput.d.ts +39 -0
  134. package/dist/components/UploadInput/UploadInput.d.ts.map +1 -0
  135. package/dist/components/UploadInput/UploadInput.js +297 -0
  136. package/dist/components/UploadInput/UploadInput.js.map +1 -0
  137. package/dist/components/index.d.ts +65 -0
  138. package/dist/components/index.d.ts.map +1 -0
  139. package/dist/index.d.ts +7 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +69 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/plugin/jiwambe-plugin.d.ts +37 -0
  144. package/dist/plugin/jiwambe-plugin.d.ts.map +1 -0
  145. package/dist/plugin/jiwambe-plugin.js +640 -0
  146. package/dist/plugin/jiwambe-plugin.js.map +1 -0
  147. package/dist/server.d.ts +22 -0
  148. package/dist/server.d.ts.map +1 -0
  149. package/dist/server.js +23 -0
  150. package/dist/server.js.map +1 -0
  151. package/dist/types/index.d.ts +103 -0
  152. package/dist/types/index.d.ts.map +1 -0
  153. package/dist/types/layout.d.ts +138 -0
  154. package/dist/types/layout.d.ts.map +1 -0
  155. package/dist/types/list.d.ts +69 -0
  156. package/dist/types/list.d.ts.map +1 -0
  157. package/dist/types/list.js +9 -0
  158. package/dist/types/list.js.map +1 -0
  159. package/dist/types/skeleton.d.ts +38 -0
  160. package/dist/types/skeleton.d.ts.map +1 -0
  161. package/dist/types/skeleton.js +13 -0
  162. package/dist/types/skeleton.js.map +1 -0
  163. package/dist/types/spacing.d.ts +105 -0
  164. package/dist/types/spacing.d.ts.map +1 -0
  165. package/dist/utils/layoutClasses.d.ts +44 -0
  166. package/dist/utils/layoutClasses.d.ts.map +1 -0
  167. package/dist/utils/layoutClasses.js +88 -0
  168. package/dist/utils/layoutClasses.js.map +1 -0
  169. package/dist/utils/responsive-props.d.ts +60 -0
  170. package/dist/utils/responsive-props.d.ts.map +1 -0
  171. package/dist/utils/responsive-props.js +184 -0
  172. package/dist/utils/responsive-props.js.map +1 -0
  173. package/dist/utils/spacing.d.ts +52 -0
  174. package/dist/utils/spacing.d.ts.map +1 -0
  175. package/dist/utils/spacing.js +625 -0
  176. package/dist/utils/spacing.js.map +1 -0
  177. package/package.json +96 -0
  178. package/tailwind.preset.d.ts +3 -0
  179. package/tailwind.preset.ts +21 -0
@@ -0,0 +1,87 @@
1
+ import { default as React } from 'react';
2
+ import { SkeletonProps, SkeletonRadius } from '../../types/skeleton';
3
+ /**
4
+ * Loading placeholder primitive. Renders an animated shimmer shape
5
+ * that communicates content is loading. Use in place of content
6
+ * while data is being fetched.
7
+ *
8
+ * Three preset sub-components are available for common use cases:
9
+ * - Skeleton.Text — single line text placeholder
10
+ * - Skeleton.Avatar — circular profile image placeholder
11
+ * - Skeleton.Card — rectangular card-shaped placeholder
12
+ *
13
+ * For custom shapes, use the Skeleton primitive directly with
14
+ * explicit width, height, and radius props.
15
+ *
16
+ * The shimmer animation uses design system colour tokens:
17
+ * background: var(--col-neutral-100), highlight: var(--col-neutral-50).
18
+ *
19
+ * @example
20
+ * // Custom shape
21
+ * <Skeleton width="100%" height="2rem" radius="xs" />
22
+ *
23
+ * @example
24
+ * // Paragraph placeholder
25
+ * <Stack spacing="space-2">
26
+ * <Skeleton.Text width="100%" />
27
+ * <Skeleton.Text width="90%" />
28
+ * <Skeleton.Text width="75%" />
29
+ * </Stack>
30
+ *
31
+ * @example
32
+ * // Profile header placeholder
33
+ * <Stack direction="row" spacing="space-3" alignItems="center">
34
+ * <Skeleton.Avatar size="2.5rem" />
35
+ * <Stack spacing="space-1">
36
+ * <Skeleton.Text width="8rem" />
37
+ * <Skeleton.Text width="5rem" size="xs" />
38
+ * </Stack>
39
+ * </Stack>
40
+ */
41
+ export declare function Skeleton({ width, height, radius, label, className, style, }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
42
+ export declare namespace Skeleton {
43
+ var Text: ({ width, size, className, style, }: SkeletonTextProps) => import("react/jsx-runtime").JSX.Element;
44
+ var Avatar: ({ size, className, style, }: SkeletonAvatarProps) => import("react/jsx-runtime").JSX.Element;
45
+ var Card: ({ width, height, radius, className, style, }: SkeletonCardProps) => import("react/jsx-runtime").JSX.Element;
46
+ }
47
+ /** Props for Skeleton.Text. Single-line text placeholder. */
48
+ interface SkeletonTextProps {
49
+ /** Width of the text placeholder. Number = rem. @default '100%' */
50
+ width?: string | number;
51
+ /**
52
+ * Typography size to match. Controls height: xs=0.75rem, sm=1rem, md=1.125rem, lg=1.5rem.
53
+ * @default 'sm'
54
+ */
55
+ size?: 'xs' | 'sm' | 'md' | 'lg';
56
+ /** Additional className. @default undefined */
57
+ className?: string;
58
+ /** Additional inline styles. @default undefined */
59
+ style?: React.CSSProperties;
60
+ }
61
+ /** Props for Skeleton.Avatar. Circular avatar placeholder. */
62
+ interface SkeletonAvatarProps {
63
+ /**
64
+ * Diameter of the avatar circle. Number = rem, string = used as-is.
65
+ * @default '2.5rem'
66
+ */
67
+ size?: string | number;
68
+ /** Additional className. @default undefined */
69
+ className?: string;
70
+ /** Additional inline styles. @default undefined */
71
+ style?: React.CSSProperties;
72
+ }
73
+ /** Props for Skeleton.Card. Rectangular card-shaped placeholder. */
74
+ interface SkeletonCardProps {
75
+ /** Width of the card. Number = rem. @default '100%' */
76
+ width?: string | number;
77
+ /** Height of the card. Number = rem. @default '8rem' */
78
+ height?: string | number;
79
+ /** Border radius token. @default 'md' */
80
+ radius?: SkeletonRadius;
81
+ /** Additional className. @default undefined */
82
+ className?: string;
83
+ /** Additional inline styles. @default undefined */
84
+ style?: React.CSSProperties;
85
+ }
86
+ export {};
87
+ //# sourceMappingURL=Skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/Skeleton/Skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAQ9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,MAAM,EACN,MAAa,EACb,KAAoB,EACpB,SAAc,EACd,KAAK,GACN,EAAE,aAAa,2CAiBf;yBAxBe,QAAQ;mDAwDrB,iBAAiB;8CAiCjB,mBAAmB;6DAqCnB,iBAAiB;;AAlGpB,6DAA6D;AAC7D,UAAU,iBAAiB;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AA8BD,8DAA8D;AAC9D,UAAU,mBAAmB;IAC3B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAuBD,oEAAoE;AACpE,UAAU,iBAAiB;IACzB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,yCAAyC;IACzC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B"}
@@ -0,0 +1,97 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { skeletonRadiusMap } from "../../types/skeleton.js";
3
+ function resolveSize(value, fallback) {
4
+ if (value === void 0) return fallback;
5
+ if (typeof value === "number") return `${value}rem`;
6
+ return value;
7
+ }
8
+ function Skeleton({
9
+ width,
10
+ height,
11
+ radius = "xs",
12
+ label = "Loading...",
13
+ className = "",
14
+ style
15
+ }) {
16
+ const internalStyle = {
17
+ width: resolveSize(width, "100%"),
18
+ height: resolveSize(height, "1rem"),
19
+ borderRadius: skeletonRadiusMap[radius],
20
+ display: "block",
21
+ ...style
22
+ };
23
+ return /* @__PURE__ */ jsx(
24
+ "div",
25
+ {
26
+ role: "status",
27
+ "aria-label": label,
28
+ className: ["jiwambe-skeleton", className].filter(Boolean).join(" "),
29
+ style: internalStyle
30
+ }
31
+ );
32
+ }
33
+ const textHeightMap = {
34
+ xs: "0.75rem",
35
+ sm: "1rem",
36
+ md: "1.125rem",
37
+ lg: "1.5rem"
38
+ };
39
+ Skeleton.Text = function SkeletonText({
40
+ width,
41
+ size = "sm",
42
+ className,
43
+ style
44
+ }) {
45
+ return /* @__PURE__ */ jsx(
46
+ Skeleton,
47
+ {
48
+ width: width ?? "100%",
49
+ height: textHeightMap[size],
50
+ radius: "xs",
51
+ label: "Loading text...",
52
+ className,
53
+ style
54
+ }
55
+ );
56
+ };
57
+ Skeleton.Avatar = function SkeletonAvatar({
58
+ size = "2.5rem",
59
+ className,
60
+ style
61
+ }) {
62
+ const resolved = typeof size === "number" ? `${size}rem` : size;
63
+ return /* @__PURE__ */ jsx(
64
+ Skeleton,
65
+ {
66
+ width: resolved,
67
+ height: resolved,
68
+ radius: "rounded",
69
+ label: "Loading avatar...",
70
+ className,
71
+ style
72
+ }
73
+ );
74
+ };
75
+ Skeleton.Card = function SkeletonCard({
76
+ width,
77
+ height = "8rem",
78
+ radius = "md",
79
+ className,
80
+ style
81
+ }) {
82
+ return /* @__PURE__ */ jsx(
83
+ Skeleton,
84
+ {
85
+ width: width ?? "100%",
86
+ height,
87
+ radius,
88
+ label: "Loading card...",
89
+ className,
90
+ style
91
+ }
92
+ );
93
+ };
94
+ export {
95
+ Skeleton
96
+ };
97
+ //# sourceMappingURL=Skeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skeleton.js","sources":["../../../src/components/Skeleton/Skeleton.tsx"],"sourcesContent":["import React from 'react';\nimport {\n skeletonRadiusMap,\n type SkeletonProps,\n type SkeletonRadius,\n} from '../../types/skeleton';\n\nfunction resolveSize(value: string | number | undefined, fallback: string): string {\n if (value === undefined) return fallback;\n if (typeof value === 'number') return `${value}rem`;\n return value;\n}\n\n/**\n * Loading placeholder primitive. Renders an animated shimmer shape\n * that communicates content is loading. Use in place of content\n * while data is being fetched.\n *\n * Three preset sub-components are available for common use cases:\n * - Skeleton.Text — single line text placeholder\n * - Skeleton.Avatar — circular profile image placeholder\n * - Skeleton.Card — rectangular card-shaped placeholder\n *\n * For custom shapes, use the Skeleton primitive directly with\n * explicit width, height, and radius props.\n *\n * The shimmer animation uses design system colour tokens:\n * background: var(--col-neutral-100), highlight: var(--col-neutral-50).\n *\n * @example\n * // Custom shape\n * <Skeleton width=\"100%\" height=\"2rem\" radius=\"xs\" />\n *\n * @example\n * // Paragraph placeholder\n * <Stack spacing=\"space-2\">\n * <Skeleton.Text width=\"100%\" />\n * <Skeleton.Text width=\"90%\" />\n * <Skeleton.Text width=\"75%\" />\n * </Stack>\n *\n * @example\n * // Profile header placeholder\n * <Stack direction=\"row\" spacing=\"space-3\" alignItems=\"center\">\n * <Skeleton.Avatar size=\"2.5rem\" />\n * <Stack spacing=\"space-1\">\n * <Skeleton.Text width=\"8rem\" />\n * <Skeleton.Text width=\"5rem\" size=\"xs\" />\n * </Stack>\n * </Stack>\n */\nexport function Skeleton({\n width,\n height,\n radius = 'xs',\n label = 'Loading...',\n className = '',\n style,\n}: SkeletonProps) {\n const internalStyle: React.CSSProperties = {\n width: resolveSize(width, '100%'),\n height: resolveSize(height, '1rem'),\n borderRadius: skeletonRadiusMap[radius],\n display: 'block',\n ...style,\n };\n\n return (\n <div\n role=\"status\"\n aria-label={label}\n className={['jiwambe-skeleton', className].filter(Boolean).join(' ')}\n style={internalStyle}\n />\n );\n}\n\n// --- Skeleton.Text ---\n\n/** Props for Skeleton.Text. Single-line text placeholder. */\ninterface SkeletonTextProps {\n /** Width of the text placeholder. Number = rem. @default '100%' */\n width?: string | number;\n /**\n * Typography size to match. Controls height: xs=0.75rem, sm=1rem, md=1.125rem, lg=1.5rem.\n * @default 'sm'\n */\n size?: 'xs' | 'sm' | 'md' | 'lg';\n /** Additional className. @default undefined */\n className?: string;\n /** Additional inline styles. @default undefined */\n style?: React.CSSProperties;\n}\n\nconst textHeightMap = {\n xs: '0.75rem',\n sm: '1rem',\n md: '1.125rem',\n lg: '1.5rem',\n};\n\n/** Single-line text loading placeholder. Height matches typography size. */\nSkeleton.Text = function SkeletonText({\n width,\n size = 'sm',\n className,\n style,\n}: SkeletonTextProps) {\n return (\n <Skeleton\n width={width ?? '100%'}\n height={textHeightMap[size]}\n radius=\"xs\"\n label=\"Loading text...\"\n className={className}\n style={style}\n />\n );\n};\n\n// --- Skeleton.Avatar ---\n\n/** Props for Skeleton.Avatar. Circular avatar placeholder. */\ninterface SkeletonAvatarProps {\n /**\n * Diameter of the avatar circle. Number = rem, string = used as-is.\n * @default '2.5rem'\n */\n size?: string | number;\n /** Additional className. @default undefined */\n className?: string;\n /** Additional inline styles. @default undefined */\n style?: React.CSSProperties;\n}\n\n/** Circular profile image loading placeholder. Always uses radius=\"rounded\". */\nSkeleton.Avatar = function SkeletonAvatar({\n size = '2.5rem',\n className,\n style,\n}: SkeletonAvatarProps) {\n const resolved = typeof size === 'number' ? `${size}rem` : size;\n return (\n <Skeleton\n width={resolved}\n height={resolved}\n radius=\"rounded\"\n label=\"Loading avatar...\"\n className={className}\n style={style}\n />\n );\n};\n\n// --- Skeleton.Card ---\n\n/** Props for Skeleton.Card. Rectangular card-shaped placeholder. */\ninterface SkeletonCardProps {\n /** Width of the card. Number = rem. @default '100%' */\n width?: string | number;\n /** Height of the card. Number = rem. @default '8rem' */\n height?: string | number;\n /** Border radius token. @default 'md' */\n radius?: SkeletonRadius;\n /** Additional className. @default undefined */\n className?: string;\n /** Additional inline styles. @default undefined */\n style?: React.CSSProperties;\n}\n\n/** Card-shaped content block loading placeholder. */\nSkeleton.Card = function SkeletonCard({\n width,\n height = '8rem',\n radius = 'md',\n className,\n style,\n}: SkeletonCardProps) {\n return (\n <Skeleton\n width={width ?? '100%'}\n height={height}\n radius={radius}\n label=\"Loading card...\"\n className={className}\n style={style}\n />\n );\n};\n"],"names":[],"mappings":";;AAOA,SAAS,YAAY,OAAoC,UAA0B;AACjF,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,KAAK;AAC9C,SAAO;AACT;AAwCO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ;AACF,GAAkB;AAChB,QAAM,gBAAqC;AAAA,IACzC,OAAO,YAAY,OAAO,MAAM;AAAA,IAChC,QAAQ,YAAY,QAAQ,MAAM;AAAA,IAClC,cAAc,kBAAkB,MAAM;AAAA,IACtC,SAAS;AAAA,IACT,GAAG;AAAA,EAAA;AAGL,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,WAAW,CAAC,oBAAoB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MACnE,OAAO;AAAA,IAAA;AAAA,EAAA;AAGb;AAmBA,MAAM,gBAAgB;AAAA,EACpB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAGA,SAAS,OAAO,SAAS,aAAa;AAAA,EACpC;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AACF,GAAsB;AACpB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO,SAAS;AAAA,MAChB,QAAQ,cAAc,IAAI;AAAA,MAC1B,QAAO;AAAA,MACP,OAAM;AAAA,MACN;AAAA,MACA;AAAA,IAAA;AAAA,EAAA;AAGN;AAkBA,SAAS,SAAS,SAAS,eAAe;AAAA,EACxC,OAAO;AAAA,EACP;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,WAAW,OAAO,SAAS,WAAW,GAAG,IAAI,QAAQ;AAC3D,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAO;AAAA,MACP,OAAM;AAAA,MACN;AAAA,MACA;AAAA,IAAA;AAAA,EAAA;AAGN;AAmBA,SAAS,OAAO,SAAS,aAAa;AAAA,EACpC;AAAA,EACA,SAAS;AAAA,EACT,SAAS;AAAA,EACT;AAAA,EACA;AACF,GAAsB;AACpB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO,SAAS;AAAA,MAChB;AAAA,MACA;AAAA,MACA,OAAM;AAAA,MACN;AAAA,MACA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -0,0 +1,3 @@
1
+ export { Skeleton } from './Skeleton';
2
+ export type { SkeletonProps, SkeletonRadius } from '../../types/skeleton';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Skeleton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * Props for the Slider component. Range input with optional labels and min/max labels.
4
+ * Supports controlled (value/onChange) or uncontrolled (defaultValue) usage. Track and
5
+ * thumb use design tokens (e.g. green for fill when not disabled).
6
+ */
7
+ export interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'value' | 'defaultValue' | 'onChange'> {
8
+ /** Optional label above the slider. @default undefined */
9
+ label?: string;
10
+ /** Supportive text below the label. @default undefined */
11
+ supportText?: string;
12
+ /** Label shown under the track at the min end (e.g. "5,000 KES"). Falls back to min. @default undefined */
13
+ minLabel?: string;
14
+ /** Label shown under the track at the max end (e.g. "255,000 KES"). Falls back to max. @default undefined */
15
+ maxLabel?: string;
16
+ /** Controlled value (number). Use with onChange. @default undefined */
17
+ value?: number;
18
+ /** Uncontrolled default value. @default min */
19
+ defaultValue?: number;
20
+ /** Called when the value changes (drag or keyboard). @default undefined */
21
+ onChange?: (value: number) => void;
22
+ /** Minimum value. @default 0 */
23
+ min?: number;
24
+ /** Maximum value. @default 100 */
25
+ max?: number;
26
+ /** Step increment. @default 1 */
27
+ step?: number;
28
+ /** Additional class name on the wrapper. @default undefined */
29
+ className?: string;
30
+ /** ID for the range input. @default undefined */
31
+ id?: string;
32
+ /** Forwarded ref for the native range input. @default undefined */
33
+ ref?: React.Ref<HTMLInputElement>;
34
+ }
35
+ /**
36
+ * Range slider with optional label, support text, and min/max value labels. Renders a
37
+ * custom track and thumb (design-token colours) with a hidden native range input for
38
+ * accessibility. Supports controlled (value/onChange) or uncontrolled (defaultValue) usage.
39
+ *
40
+ * @example
41
+ * <Slider label="Amount" min={0} max={100} defaultValue={50} minLabel="0" maxLabel="100" />
42
+ *
43
+ * @example
44
+ * <Slider label="Price" value={price} onChange={setPrice} min={5000} max={255000} step={1000} minLabel="5,000 KES" maxLabel="255,000 KES" />
45
+ */
46
+ export declare function Slider({ label, supportText, minLabel, maxLabel, value: valueProp, defaultValue, onChange, min, max, step, disabled, className, id: idProp, ref, ...rest }: SliderProps): import("react/jsx-runtime").JSX.Element;
47
+ //# sourceMappingURL=Slider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAM1D;;;;GAIG;AACH,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC;IACzG,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2GAA2G;IAC3G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,mEAAmE;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;CACnC;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,KAAK,EAAE,SAAS,EAChB,YAAY,EACZ,QAAQ,EACR,GAAO,EACP,GAAS,EACT,IAAQ,EACR,QAAgB,EAChB,SAAS,EACT,EAAE,EAAE,MAAM,EACV,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,2CA+Hb"}
@@ -0,0 +1,147 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import React, { useId, useRef, useCallback } from "react";
4
+ const THUMB = 24;
5
+ const TRACK = 1.25;
6
+ function Slider({
7
+ label,
8
+ supportText,
9
+ minLabel,
10
+ maxLabel,
11
+ value: valueProp,
12
+ defaultValue,
13
+ onChange,
14
+ min = 0,
15
+ max = 100,
16
+ step = 1,
17
+ disabled = false,
18
+ className,
19
+ id: idProp,
20
+ ref,
21
+ ...rest
22
+ }) {
23
+ const autoId = useId();
24
+ const id = idProp ?? autoId;
25
+ const isControlled = valueProp !== void 0;
26
+ const [internal, setInternal] = React.useState(defaultValue ?? min);
27
+ const value = isControlled ? valueProp : internal;
28
+ const [focused, setFocused] = React.useState(false);
29
+ const trackRef = useRef(null);
30
+ const handleChange = useCallback(
31
+ (e) => {
32
+ const next = Number(e.target.value);
33
+ if (!isControlled) setInternal(next);
34
+ onChange == null ? void 0 : onChange(next);
35
+ },
36
+ [isControlled, onChange]
37
+ );
38
+ const percent = max > min ? (value - min) / (max - min) * 100 : 0;
39
+ const pct = Math.min(100, Math.max(0, percent));
40
+ const thumbBg = disabled ? "#ABB5B3" : "#005748";
41
+ const filledBg = disabled ? "#ABB5B3" : "#005748";
42
+ const unfilledBg = "#CED3D2";
43
+ return /* @__PURE__ */ jsxs(
44
+ "div",
45
+ {
46
+ className: `flex flex-col gap-space-2 w-full ${className ?? ""}`,
47
+ children: [
48
+ (label || supportText) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-space-1", children: [
49
+ label && /* @__PURE__ */ jsx(
50
+ "label",
51
+ {
52
+ htmlFor: id,
53
+ className: `text-form-label ${disabled ? "text-text-disabled" : "text-text-primary"}`,
54
+ children: label
55
+ }
56
+ ),
57
+ supportText && /* @__PURE__ */ jsx(
58
+ "p",
59
+ {
60
+ className: `text-text-xs ${disabled ? "text-text-disabled" : "text-text-secondary"}`,
61
+ children: supportText
62
+ }
63
+ )
64
+ ] }),
65
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-space-2", children: [
66
+ /* @__PURE__ */ jsxs(
67
+ "div",
68
+ {
69
+ ref: trackRef,
70
+ className: "relative w-full",
71
+ style: { height: THUMB },
72
+ children: [
73
+ /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ className: "absolute left-0 right-0 rounded-full",
77
+ style: {
78
+ height: TRACK,
79
+ top: (THUMB - TRACK) / 2,
80
+ background: `linear-gradient(to right, ${filledBg} ${pct}%, ${unfilledBg} ${pct}%)`
81
+ }
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsx(
85
+ "div",
86
+ {
87
+ className: "absolute rounded-rad-xs transition-shadow duration-150",
88
+ style: {
89
+ width: THUMB,
90
+ height: THUMB,
91
+ top: 0,
92
+ background: thumbBg,
93
+ left: `calc(${pct}% - ${pct / 100 * THUMB}px)`,
94
+ boxShadow: focused && !disabled ? "0 0 0 2px #fff, 0 0 0 4px var(--color-border-focus, #005748)" : "none"
95
+ }
96
+ }
97
+ ),
98
+ /* @__PURE__ */ jsx(
99
+ "input",
100
+ {
101
+ ref,
102
+ type: "range",
103
+ id,
104
+ min,
105
+ max,
106
+ step,
107
+ value,
108
+ disabled,
109
+ onChange: handleChange,
110
+ onFocus: () => setFocused(true),
111
+ onBlur: () => setFocused(false),
112
+ "aria-valuemin": min,
113
+ "aria-valuemax": max,
114
+ "aria-valuenow": value,
115
+ className: "absolute inset-0 w-full opacity-0 cursor-pointer disabled:cursor-not-allowed",
116
+ style: { height: THUMB, margin: 0 },
117
+ ...rest
118
+ }
119
+ )
120
+ ]
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-text-sm", children: [
124
+ /* @__PURE__ */ jsx(
125
+ "span",
126
+ {
127
+ className: disabled ? "text-text-disabled" : "text-text-primary",
128
+ children: minLabel ?? min
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsx(
132
+ "span",
133
+ {
134
+ className: disabled ? "text-text-disabled" : "text-text-primary",
135
+ children: maxLabel ?? max
136
+ }
137
+ )
138
+ ] })
139
+ ] })
140
+ ]
141
+ }
142
+ );
143
+ }
144
+ export {
145
+ Slider
146
+ };
147
+ //# sourceMappingURL=Slider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slider.js","sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["'use client';\n\nimport React, { useId, useCallback, useRef } from 'react';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the Slider component. Range input with optional labels and min/max labels.\n * Supports controlled (value/onChange) or uncontrolled (defaultValue) usage. Track and\n * thumb use design tokens (e.g. green for fill when not disabled).\n */\nexport interface SliderProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'value' | 'defaultValue' | 'onChange'> {\n /** Optional label above the slider. @default undefined */\n label?: string;\n /** Supportive text below the label. @default undefined */\n supportText?: string;\n /** Label shown under the track at the min end (e.g. \"5,000 KES\"). Falls back to min. @default undefined */\n minLabel?: string;\n /** Label shown under the track at the max end (e.g. \"255,000 KES\"). Falls back to max. @default undefined */\n maxLabel?: string;\n /** Controlled value (number). Use with onChange. @default undefined */\n value?: number;\n /** Uncontrolled default value. @default min */\n defaultValue?: number;\n /** Called when the value changes (drag or keyboard). @default undefined */\n onChange?: (value: number) => void;\n /** Minimum value. @default 0 */\n min?: number;\n /** Maximum value. @default 100 */\n max?: number;\n /** Step increment. @default 1 */\n step?: number;\n /** Additional class name on the wrapper. @default undefined */\n className?: string;\n /** ID for the range input. @default undefined */\n id?: string;\n /** Forwarded ref for the native range input. @default undefined */\n ref?: React.Ref<HTMLInputElement>;\n}\n\nconst THUMB = 24;\nconst TRACK = 1.25;\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Range slider with optional label, support text, and min/max value labels. Renders a\n * custom track and thumb (design-token colours) with a hidden native range input for\n * accessibility. Supports controlled (value/onChange) or uncontrolled (defaultValue) usage.\n *\n * @example\n * <Slider label=\"Amount\" min={0} max={100} defaultValue={50} minLabel=\"0\" maxLabel=\"100\" />\n *\n * @example\n * <Slider label=\"Price\" value={price} onChange={setPrice} min={5000} max={255000} step={1000} minLabel=\"5,000 KES\" maxLabel=\"255,000 KES\" />\n */\nexport function Slider({\n label,\n supportText,\n minLabel,\n maxLabel,\n value: valueProp,\n defaultValue,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n className,\n id: idProp,\n ref,\n ...rest\n}: SliderProps) {\n const autoId = useId();\n const id = idProp ?? autoId;\n\n const isControlled = valueProp !== undefined;\n const [internal, setInternal] = React.useState(defaultValue ?? min);\n const value = isControlled ? valueProp : internal;\n const [focused, setFocused] = React.useState(false);\n\n const trackRef = useRef<HTMLDivElement>(null);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const next = Number(e.target.value);\n if (!isControlled) setInternal(next);\n onChange?.(next);\n },\n [isControlled, onChange],\n );\n\n const percent = max > min ? ((value - min) / (max - min)) * 100 : 0;\n const pct = Math.min(100, Math.max(0, percent));\n\n const thumbBg = disabled ? '#ABB5B3' : '#005748';\n const filledBg = disabled ? '#ABB5B3' : '#005748';\n const unfilledBg = '#CED3D2';\n\n return (\n <div\n className={`flex flex-col gap-space-2 w-full ${className ?? ''}`}\n >\n {(label || supportText) && (\n <div className=\"flex flex-col gap-space-1\">\n {label && (\n <label\n htmlFor={id}\n className={`text-form-label ${\n disabled ? 'text-text-disabled' : 'text-text-primary'\n }`}\n >\n {label}\n </label>\n )}\n {supportText && (\n <p\n className={`text-text-xs ${\n disabled ? 'text-text-disabled' : 'text-text-secondary'\n }`}\n >\n {supportText}\n </p>\n )}\n </div>\n )}\n\n <div className=\"flex flex-col gap-space-2\">\n <div\n ref={trackRef}\n className=\"relative w-full\"\n style={{ height: THUMB }}\n >\n {/* Track — thin line centered at 50% of the 24px container */}\n <div\n className=\"absolute left-0 right-0 rounded-full\"\n style={{\n height: TRACK,\n top: (THUMB - TRACK) / 2,\n background: `linear-gradient(to right, ${filledBg} ${pct}%, ${unfilledBg} ${pct}%)`,\n }}\n />\n\n {/* Thumb — 24×24, rad-xs (6px), centered vertically */}\n <div\n className=\"absolute rounded-rad-xs transition-shadow duration-150\"\n style={{\n width: THUMB,\n height: THUMB,\n top: 0,\n background: thumbBg,\n left: `calc(${pct}% - ${(pct / 100) * THUMB}px)`,\n boxShadow: focused && !disabled\n ? '0 0 0 2px #fff, 0 0 0 4px var(--color-border-focus, #005748)'\n : 'none',\n }}\n />\n\n {/* Hidden native input for accessibility & interaction */}\n <input\n ref={ref}\n type=\"range\"\n id={id}\n min={min}\n max={max}\n step={step}\n value={value}\n disabled={disabled}\n onChange={handleChange}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n className=\"absolute inset-0 w-full opacity-0 cursor-pointer disabled:cursor-not-allowed\"\n style={{ height: THUMB, margin: 0 }}\n {...rest}\n />\n </div>\n\n <div className=\"flex justify-between text-text-sm\">\n <span\n className={\n disabled ? 'text-text-disabled' : 'text-text-primary'\n }\n >\n {minLabel ?? min}\n </span>\n <span\n className={\n disabled ? 'text-text-disabled' : 'text-text-primary'\n }\n >\n {maxLabel ?? max}\n </span>\n </div>\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":";;;AA2CA;AACA;AAiBO;AAAgB;AACrB;AACA;AACA;AACA;AACO;AACP;AACA;AACM;AACA;AACC;AACI;AACX;AACI;AACJ;AAEF;AACE;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AAAqB;AAEjB;AACA;AACA;AAAW;AACb;AACuB;AAGzB;AACA;AAEA;AACA;AACA;AAEA;AACE;AAAC;AAAA;AAC+D;AAE5D;AAEG;AACC;AAAC;AAAA;AACU;AAGT;AAEC;AAAA;AAAA;AAIH;AAAC;AAAA;AAGC;AAEC;AAAA;AAAA;AAGP;AAIA;AAAA;AAAC;AAAA;AACM;AACK;AACO;AAGjB;AAAA;AAAC;AAAA;AACW;AACH;AACG;AACe;AACwD;AAAA;AACjF;AAAA;AAIF;AAAC;AAAA;AACW;AACH;AACE;AACC;AACH;AACO;AAC+B;AAGvC;AAAA;AACN;AAAA;AAIF;AAAC;AAAA;AACC;AACK;AACL;AACA;AACA;AACA;AACA;AACA;AACU;AACoB;AACA;AACf;AACA;AACA;AACL;AACsB;AAC5B;AAAA;AAAA;AACN;AAAA;AAAA;AAIA;AAAA;AAAC;AAAA;AAEqC;AAGvB;AAAA;AAAA;AAEf;AAAC;AAAA;AAEqC;AAGvB;AAAA;AAAA;AAEjB;AACF;AAAA;AAAA;AAGN;;;;"}
@@ -0,0 +1,145 @@
1
+ import { default as React } from 'react';
2
+ import { SpacingProps, SpacingToken, GapProps } from '../../types/spacing';
3
+ import { DimensionProps } from '../../utils/responsive-props';
4
+ import { StackLayoutProps, AlignItemsValue, JustifyContentValue } from '../../types/layout';
5
+ import { StackAlign, StackJustify } from '../../utils/spacing';
6
+ export type { StackAlign, StackJustify } from '../../utils/spacing';
7
+ /** Flex direction for Stack: column (vertical) or row (horizontal). */
8
+ export type StackDirection = 'column' | 'row';
9
+ /**
10
+ * Tailwind display utility class values accepted by Stack's `display` prop.
11
+ * When provided, this replaces the default hardcoded `flex` base class so
12
+ * that responsive visibility utilities (e.g. `className="hidden lg:flex"`)
13
+ * can work correctly without specificity conflicts.
14
+ *
15
+ * @example
16
+ * // Visible only at lg+ (940px)
17
+ * <Stack display="hidden" className="lg:flex" direction="row">…</Stack>
18
+ *
19
+ * @example
20
+ * // Always flex (default, no prop needed)
21
+ * <Stack direction="row">…</Stack>
22
+ */
23
+ export type StackDisplay = 'flex' | 'hidden' | 'block' | 'inline-flex' | 'inline-block' | 'inline' | 'grid' | 'inline-grid' | 'contents';
24
+ /**
25
+ * Props for the Stack component. Extends SpacingProps, StackLayoutProps
26
+ * (alignItems, justifyContent), and div attributes.
27
+ */
28
+ export interface StackProps extends SpacingProps, GapProps, DimensionProps, StackLayoutProps, Omit<React.HTMLAttributes<HTMLDivElement>, 'display'> {
29
+ /**
30
+ * Flex direction. Controls whether children are stacked vertically
31
+ * or arranged horizontally.
32
+ * @default 'column'
33
+ */
34
+ direction?: StackDirection;
35
+ /**
36
+ * Gap between direct children using CSS gap — not margin. Accepts any
37
+ * SpacingToken string. Spacing is consistent regardless of child
38
+ * visibility, since gap behaves differently from margin with hidden children.
39
+ * @default undefined
40
+ */
41
+ spacing?: SpacingToken;
42
+ /**
43
+ * Shorthand for aligning children on the cross axis. Accepts Jiwambe
44
+ * shorthand values ('start', 'center', 'end', 'stretch'). When both
45
+ * align and alignItems are provided, alignItems takes precedence.
46
+ * @see alignItems
47
+ */
48
+ align?: StackAlign;
49
+ /**
50
+ * CSS-value alias for the align prop. Cross-axis alignment. Takes
51
+ * precedence over align when both are provided. Prefer for clarity.
52
+ * @default undefined
53
+ * @see align
54
+ */
55
+ alignItems?: AlignItemsValue;
56
+ /**
57
+ * Shorthand for distributing children along the main axis. Accepts
58
+ * Jiwambe shorthand ('start', 'center', 'end', 'between', 'around').
59
+ * When both justify and justifyContent are provided, justifyContent
60
+ * takes precedence.
61
+ * @see justifyContent
62
+ */
63
+ justify?: StackJustify;
64
+ /**
65
+ * CSS-value alias for the justify prop. Main-axis distribution. Takes
66
+ * precedence over justify when both are provided.
67
+ * @default undefined
68
+ * @see justify
69
+ */
70
+ justifyContent?: JustifyContentValue;
71
+ /**
72
+ * When true, children wrap to the next line when the Stack overflows
73
+ * its container. Sets flex-wrap: wrap. Only meaningful when
74
+ * direction="row".
75
+ * @default false
76
+ */
77
+ wrap?: boolean;
78
+ /**
79
+ * The HTML element to render as the root. Use for semantic correctness
80
+ * (e.g. as="nav", as="section").
81
+ * @default 'div'
82
+ */
83
+ as?: React.ElementType;
84
+ /** Forwarded ref for the root element. @default undefined */
85
+ ref?: React.Ref<HTMLDivElement>;
86
+ /** Child content. @default undefined */
87
+ children?: React.ReactNode;
88
+ /**
89
+ * Controls the CSS display value of the root element via a Tailwind utility
90
+ * class. When provided, replaces the default `flex` base class so that
91
+ * responsive overrides in `className` work without CSS specificity conflicts.
92
+ *
93
+ * Use this together with a responsive class in `className` to implement
94
+ * responsive show/hide:
95
+ *
96
+ * @example
97
+ * // Hidden by default, shown as flex at lg (940px+)
98
+ * <Stack display="hidden" className="lg:flex" direction="row" align="center">…</Stack>
99
+ *
100
+ * @example
101
+ * // Shown as flex from sm (600px), hidden again at lg (940px+)
102
+ * <Stack display="hidden" className="sm:flex lg:hidden" direction="row">…</Stack>
103
+ *
104
+ * @default undefined — falls back to the hardcoded 'flex' base class
105
+ */
106
+ display?: StackDisplay;
107
+ }
108
+ /**
109
+ * One-dimensional flex layout component. Stacks children vertically
110
+ * (default) or horizontally with consistent spacing between them.
111
+ *
112
+ * Stack is specifically for linear sequences of children. For
113
+ * two-dimensional or multi-column layouts, use Grid. For a
114
+ * general-purpose wrapper, use Box.
115
+ *
116
+ * Spacing between children is controlled by the spacing prop (CSS gap),
117
+ * not by margin on children. This means spacing is consistent regardless
118
+ * of which children are visible.
119
+ *
120
+ * @example
121
+ * // Vertical stack — form fields, card content
122
+ * <Stack spacing="space-4">
123
+ * <Input label="Name" />
124
+ * <Input label="Email" />
125
+ * <Button>Submit</Button>
126
+ * </Stack>
127
+ *
128
+ * @example
129
+ * // Horizontal stack — toolbar, inline actions
130
+ * <Stack direction="row" spacing="space-3" alignItems="center">
131
+ * <Icon />
132
+ * <Text>Label</Text>
133
+ * </Stack>
134
+ *
135
+ * @example
136
+ * // Responsive visibility — hidden on mobile, flex at lg+
137
+ * <Stack display="hidden" className="lg:flex" direction="row" align="center">
138
+ * …desktop nav…
139
+ * </Stack>
140
+ */
141
+ export declare function Stack({ direction, spacing, align, justify, alignItems, justifyContent, wrap, as: Tag, children, className, ref, display, ...rest }: StackProps): import("react/jsx-runtime").JSX.Element;
142
+ export declare namespace Stack {
143
+ var displayName: string;
144
+ }
145
+ //# sourceMappingURL=Stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../src/components/Stack/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEpE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEpE,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE9C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,aAAa,GACb,cAAc,GACd,QAAQ,GACR,MAAM,GACN,aAAa,GACb,UAAU,CAAC;AAEf;;;GAGG;AACH,MAAM,WAAW,UACf,SAAQ,YAAY,EACpB,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IACrD;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,EAAE,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IACvB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,KAAK,CAAC,EACpB,SAAoB,EACpB,OAAO,EACP,KAAK,EACL,OAAO,EACP,UAAU,EACV,cAAc,EACd,IAAY,EACZ,EAAE,EAAE,GAAW,EACf,QAAQ,EACR,SAAc,EACd,GAAG,EACH,OAAO,EACP,GAAG,IAAI,EACR,EAAE,UAAU,2CAqDZ;yBAnEe,KAAK"}
@@ -0,0 +1,80 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { resolveSpacing, gapMap, alignMap, justifyMap } from "../../utils/spacing.js";
3
+ import { alignItemsMap, justifyContentMap } from "../../utils/layoutClasses.js";
4
+ function Stack({
5
+ direction = "column",
6
+ spacing,
7
+ align,
8
+ justify,
9
+ alignItems,
10
+ justifyContent,
11
+ wrap = false,
12
+ as: Tag = "div",
13
+ children,
14
+ className = "",
15
+ ref,
16
+ display,
17
+ ...rest
18
+ }) {
19
+ const directionClass = direction === "row" ? "flex-row" : "flex-col";
20
+ const spacingClass = spacing !== void 0 ? gapMap[spacing] : "";
21
+ const alignClass = align ? alignMap[align] : "";
22
+ const justifyClass = justify ? justifyMap[justify] : "";
23
+ const alignItemsClass = alignItems !== void 0 ? alignItemsMap[alignItems] : "";
24
+ const justifyContentClass = justifyContent !== void 0 ? justifyContentMap[justifyContent] : "";
25
+ const wrapClass = wrap ? "flex-wrap" : "";
26
+ const spacingPropsClasses = resolveSpacing(rest);
27
+ const displayClass = display !== void 0 ? display : "flex";
28
+ const classes = [
29
+ displayClass,
30
+ directionClass,
31
+ spacingClass,
32
+ alignClass,
33
+ justifyClass,
34
+ alignItemsClass,
35
+ justifyContentClass,
36
+ wrapClass,
37
+ spacingPropsClasses,
38
+ className
39
+ ].filter(Boolean).join(" ");
40
+ const {
41
+ p,
42
+ px,
43
+ py,
44
+ pt,
45
+ pb,
46
+ pl,
47
+ pr,
48
+ m,
49
+ mx,
50
+ my,
51
+ mt,
52
+ mb,
53
+ ml,
54
+ mr,
55
+ width,
56
+ height,
57
+ minWidth,
58
+ minHeight,
59
+ maxWidth,
60
+ maxHeight,
61
+ gap,
62
+ rowGap,
63
+ columnGap,
64
+ ...domRest
65
+ } = rest;
66
+ const dimensionStyle = {};
67
+ if (width !== void 0) dimensionStyle.width = typeof width === "string" ? width : void 0;
68
+ if (height !== void 0) dimensionStyle.height = typeof height === "string" ? height : void 0;
69
+ if (minWidth !== void 0) dimensionStyle.minWidth = typeof minWidth === "string" ? minWidth : void 0;
70
+ if (minHeight !== void 0) dimensionStyle.minHeight = typeof minHeight === "string" ? minHeight : void 0;
71
+ if (maxWidth !== void 0) dimensionStyle.maxWidth = typeof maxWidth === "string" ? maxWidth : void 0;
72
+ if (maxHeight !== void 0) dimensionStyle.maxHeight = typeof maxHeight === "string" ? maxHeight : void 0;
73
+ const inlineStyle = Object.keys(dimensionStyle).length > 0 ? dimensionStyle : void 0;
74
+ return /* @__PURE__ */ jsx(Tag, { ref, className: classes, style: inlineStyle, ...domRest, children });
75
+ }
76
+ Stack.displayName = "Stack";
77
+ export {
78
+ Stack
79
+ };
80
+ //# sourceMappingURL=Stack.js.map