blixify-ui-web-mcp 0.1.1

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 (245) hide show
  1. package/README.md +5 -0
  2. package/lib/components/action/button/README.md +75 -0
  3. package/lib/components/action/button/button.stories.tsx +138 -0
  4. package/lib/components/action/buttonGroup/README.md +79 -0
  5. package/lib/components/action/buttonGroup/buttonGroup.stories.tsx +104 -0
  6. package/lib/components/action/iconButton/README.md +39 -0
  7. package/lib/components/action/iconButton/iconButton.stories.tsx +22 -0
  8. package/lib/components/action/radioList/README.md +98 -0
  9. package/lib/components/action/radioList/radioList.stories.tsx +181 -0
  10. package/lib/components/action/slider/README.md +86 -0
  11. package/lib/components/action/slider/slider.stories.tsx +133 -0
  12. package/lib/components/action/textButton/README.md +34 -0
  13. package/lib/components/action/textButton/textButton.stories.tsx +16 -0
  14. package/lib/components/action/toggle/README.md +39 -0
  15. package/lib/components/action/toggle/toggle.stories.tsx +23 -0
  16. package/lib/components/advanced/collapse/README.md +106 -0
  17. package/lib/components/advanced/collapse/collapse.stories.tsx +165 -0
  18. package/lib/components/advanced/infoWindow/README.md +69 -0
  19. package/lib/components/advanced/infoWindow/infoWindow.stories.tsx +112 -0
  20. package/lib/components/advanced/popUp/README.md +95 -0
  21. package/lib/components/advanced/popUp/popUp.stories.tsx +189 -0
  22. package/lib/components/auth/bareSignIn/README.md +78 -0
  23. package/lib/components/auth/bareSignIn/bareSignIn.stories.tsx +141 -0
  24. package/lib/components/auth/bareSignUp/README.md +130 -0
  25. package/lib/components/auth/bareSignUp/bareSignUp.stories.tsx +159 -0
  26. package/lib/components/auth/signIn/README.md +53 -0
  27. package/lib/components/auth/signIn/signIn.stories.tsx +120 -0
  28. package/lib/components/auth/signUp/README.md +136 -0
  29. package/lib/components/auth/signUp/signUp.stories.tsx +193 -0
  30. package/lib/components/chart/README.md +13 -0
  31. package/lib/components/chart/areaChart/README.md +133 -0
  32. package/lib/components/chart/areaChart/areaChart.stories.tsx +199 -0
  33. package/lib/components/chart/barChart/README.md +193 -0
  34. package/lib/components/chart/barChart/barChart.stories.tsx +318 -0
  35. package/lib/components/chart/boxPlotChart/README.md +124 -0
  36. package/lib/components/chart/boxPlotChart/boxPlotChart.stories.tsx +104 -0
  37. package/lib/components/chart/bubbleChart/README.md +166 -0
  38. package/lib/components/chart/bubbleChart/bubbleChart.stories.tsx +144 -0
  39. package/lib/components/chart/card/README.md +107 -0
  40. package/lib/components/chart/card/card.stories.tsx +89 -0
  41. package/lib/components/chart/ganttChart/README.md +142 -0
  42. package/lib/components/chart/ganttChart/ganttChart.stories.tsx +138 -0
  43. package/lib/components/chart/heatmapChart/README.md +125 -0
  44. package/lib/components/chart/heatmapChart/heatmapChart.stories.tsx +106 -0
  45. package/lib/components/chart/lineChart/README.md +140 -0
  46. package/lib/components/chart/lineChart/lineChart.stories.tsx +152 -0
  47. package/lib/components/chart/pieChart/README.md +117 -0
  48. package/lib/components/chart/pieChart/pieChart.stories.tsx +180 -0
  49. package/lib/components/chart/polarAreaChart/README.md +126 -0
  50. package/lib/components/chart/polarAreaChart/polarAreaChart.stories.tsx +106 -0
  51. package/lib/components/chart/radarChart/README.md +57 -0
  52. package/lib/components/chart/radarChart/radarChart.stories.tsx +36 -0
  53. package/lib/components/chart/radialBar/README.md +152 -0
  54. package/lib/components/chart/radialBar/radialChart.stories.tsx +136 -0
  55. package/lib/components/chart/rangeBarChart/README.md +323 -0
  56. package/lib/components/chart/rangeBarChart/rangeBarChart.stories.tsx +208 -0
  57. package/lib/components/chart/statsCard/README.md +97 -0
  58. package/lib/components/chart/statsCard/statsCard.stories.tsx +183 -0
  59. package/lib/components/chart/treemapChart/README.md +142 -0
  60. package/lib/components/chart/treemapChart/treemapChart.stories.tsx +122 -0
  61. package/lib/components/chat/chatAnchor/README.md +113 -0
  62. package/lib/components/chat/chatAnchor/chatAnchor.stories.tsx +156 -0
  63. package/lib/components/chat/chatBase/README.md +223 -0
  64. package/lib/components/chat/chatBase/chatBase.stories.tsx +306 -0
  65. package/lib/components/chat/chatDashboard/README.md +161 -0
  66. package/lib/components/chat/chatDashboard/chatDashboard.stories.tsx +154 -0
  67. package/lib/components/data/dataGraph/README.md +13 -0
  68. package/lib/components/data/dataGraph/dataGraph.stories.tsx +84 -0
  69. package/lib/components/data/dataReference/README.md +62 -0
  70. package/lib/components/data/dataReference/dataReference.stories.tsx +53 -0
  71. package/lib/components/data/dataTemplate/README.md +903 -0
  72. package/lib/components/data/dataTemplate/dataModule.stories.tsx +196 -0
  73. package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +337 -0
  74. package/lib/components/data/dataWrapper/README.md +1077 -0
  75. package/lib/components/data/dataWrapper/dataWrapper.stories.tsx +831 -0
  76. package/lib/components/data/queryForm/README.md +56 -0
  77. package/lib/components/data/queryForm/queryForm.stories.tsx +85 -0
  78. package/lib/components/data/readQuery/README.md +282 -0
  79. package/lib/components/data/readQuery/readQuery.stories.tsx +256 -0
  80. package/lib/components/data/readQueryHoc/README.md +89 -0
  81. package/lib/components/data/readQueryHoc/readQueryHoc.stories.tsx +33 -0
  82. package/lib/components/data/writeQuery/README.md +178 -0
  83. package/lib/components/data/writeQuery/writeQuery.stories.tsx +209 -0
  84. package/lib/components/design/actionSection/README.md +47 -0
  85. package/lib/components/design/actionSection/actionSection.stories.tsx +74 -0
  86. package/lib/components/design/banner/README.md +43 -0
  87. package/lib/components/design/banner/banner.stories.tsx +34 -0
  88. package/lib/components/design/bannerAction/README.md +44 -0
  89. package/lib/components/design/bannerAction/bannerAction.stories.tsx +25 -0
  90. package/lib/components/design/blogSection/README.md +111 -0
  91. package/lib/components/design/blogSection/blogSection.stories.tsx +72 -0
  92. package/lib/components/design/carouselSection/README.md +82 -0
  93. package/lib/components/design/carouselSection/carouselSection.stories.tsx +52 -0
  94. package/lib/components/design/designList/README.md +60 -0
  95. package/lib/components/design/designList/designList.stories.tsx +44 -0
  96. package/lib/components/design/faq/README.md +121 -0
  97. package/lib/components/design/faq/faq.stories.tsx +103 -0
  98. package/lib/components/design/fileGrid/README.md +87 -0
  99. package/lib/components/design/fileGrid/fileGrid.stories.tsx +110 -0
  100. package/lib/components/design/fileViewer/README.md +40 -0
  101. package/lib/components/design/fileViewer/fileViewer.stories.tsx +28 -0
  102. package/lib/components/design/footerSection/README.md +62 -0
  103. package/lib/components/design/footerSection/footerSection.stories.tsx +84 -0
  104. package/lib/components/design/googleReview/README.md +45 -0
  105. package/lib/components/design/googleReview/googleReview.stories.tsx +33 -0
  106. package/lib/components/design/heroSection/README.md +48 -0
  107. package/lib/components/design/heroSection/heroSection.stories.tsx +85 -0
  108. package/lib/components/design/iconList/README.md +60 -0
  109. package/lib/components/design/iconList/iconList.stories.tsx +41 -0
  110. package/lib/components/design/imageGallery/README.md +56 -0
  111. package/lib/components/design/imageGallery/imageGallery.stories.tsx +45 -0
  112. package/lib/components/design/imageZoom/README.md +47 -0
  113. package/lib/components/design/imageZoom/imageZoom.stories.tsx +30 -0
  114. package/lib/components/design/leftContent/README.md +47 -0
  115. package/lib/components/design/leftContent/leftContent.stories.tsx +32 -0
  116. package/lib/components/design/logoCloud/README.md +42 -0
  117. package/lib/components/design/logoCloud/logoCloud.stories.tsx +44 -0
  118. package/lib/components/design/onboarding/README.md +100 -0
  119. package/lib/components/design/onboarding/onboarding.stories.tsx +113 -0
  120. package/lib/components/design/pricing/README.md +112 -0
  121. package/lib/components/design/pricing/pricing.stories.tsx +86 -0
  122. package/lib/components/design/rightContent/README.md +47 -0
  123. package/lib/components/design/rightContent/rightContent.stories.tsx +32 -0
  124. package/lib/components/design/sectionList/README.md +51 -0
  125. package/lib/components/design/sectionList/sectionList.stories.tsx +35 -0
  126. package/lib/components/design/teams/README.md +62 -0
  127. package/lib/components/design/teams/teams.stories.tsx +61 -0
  128. package/lib/components/display/alert/README.md +82 -0
  129. package/lib/components/display/alert/alert.stories.tsx +71 -0
  130. package/lib/components/display/calendar/README.md +113 -0
  131. package/lib/components/display/calendar/calendar.stories.tsx +159 -0
  132. package/lib/components/display/clipboard/README.md +36 -0
  133. package/lib/components/display/clipboard/clipboard.stories.tsx +32 -0
  134. package/lib/components/display/detailList/README.md +61 -0
  135. package/lib/components/display/detailList/detailList.stories.tsx +131 -0
  136. package/lib/components/display/drawer/README.md +74 -0
  137. package/lib/components/display/drawer/drawer.stories.tsx +66 -0
  138. package/lib/components/display/emptyState/README.md +38 -0
  139. package/lib/components/display/emptyState/emptyState.stories.tsx +22 -0
  140. package/lib/components/display/feeds/README.md +80 -0
  141. package/lib/components/display/feeds/feeds.stories.tsx +75 -0
  142. package/lib/components/display/flexTable/README.md +160 -0
  143. package/lib/components/display/flexTable/flexTable.stories.tsx +313 -0
  144. package/lib/components/display/grid/README.md +121 -0
  145. package/lib/components/display/grid/grid.stories.tsx +234 -0
  146. package/lib/components/display/kanban/README.md +78 -0
  147. package/lib/components/display/kanban/kanban.stories.tsx +133 -0
  148. package/lib/components/display/list/README.md +109 -0
  149. package/lib/components/display/list/list.stories.tsx +188 -0
  150. package/lib/components/display/loading/README.md +25 -0
  151. package/lib/components/display/loading/loading.stories.tsx +15 -0
  152. package/lib/components/display/mapView/README.md +99 -0
  153. package/lib/components/display/mapView/mapView.stories.tsx +225 -0
  154. package/lib/components/display/modal/README.md +43 -0
  155. package/lib/components/display/modal/modal.stories.tsx +81 -0
  156. package/lib/components/display/notification/README.md +43 -0
  157. package/lib/components/display/notification/notification.stories.tsx +30 -0
  158. package/lib/components/display/progress/README.md +25 -0
  159. package/lib/components/display/progress/progress.stories.tsx +15 -0
  160. package/lib/components/display/stepper/README.md +96 -0
  161. package/lib/components/display/stepper/stepper.stories.tsx +175 -0
  162. package/lib/components/display/table/README.md +176 -0
  163. package/lib/components/display/table/table.stories.tsx +330 -0
  164. package/lib/components/display/tag/README.md +74 -0
  165. package/lib/components/display/tag/tag.stories.tsx +79 -0
  166. package/lib/components/input/address/README.md +132 -0
  167. package/lib/components/input/address/address.stories.tsx +147 -0
  168. package/lib/components/input/canvas/README.md +131 -0
  169. package/lib/components/input/canvas/canvas.stories.tsx +165 -0
  170. package/lib/components/input/checkbox/README.md +61 -0
  171. package/lib/components/input/checkbox/checkbox.stories.tsx +30 -0
  172. package/lib/components/input/datePicker/README.md +124 -0
  173. package/lib/components/input/datePicker/datePicker.stories.tsx +197 -0
  174. package/lib/components/input/form/README.md +55 -0
  175. package/lib/components/input/form/form.stories.tsx +143 -0
  176. package/lib/components/input/markdown/README.md +146 -0
  177. package/lib/components/input/markdown/markdown.stories.tsx +40 -0
  178. package/lib/components/input/monthYearPicker/README.md +69 -0
  179. package/lib/components/input/monthYearPicker/monthYearPicker.stories.tsx +47 -0
  180. package/lib/components/input/netPromoterScore/README.md +52 -0
  181. package/lib/components/input/netPromoterScore/netPromoterScore.stories.tsx +30 -0
  182. package/lib/components/input/rating/README.md +51 -0
  183. package/lib/components/input/rating/rating.stories.tsx +30 -0
  184. package/lib/components/input/select/README.md +108 -0
  185. package/lib/components/input/select/select.stories.tsx +286 -0
  186. package/lib/components/input/signature/README.md +106 -0
  187. package/lib/components/input/signature/signature.stories.tsx +188 -0
  188. package/lib/components/input/textArea/README.md +55 -0
  189. package/lib/components/input/textArea/textArea.stories.tsx +30 -0
  190. package/lib/components/input/textInput/README.md +81 -0
  191. package/lib/components/input/textInput/textinput.stories.tsx +231 -0
  192. package/lib/components/input/uploadInput/README.md +134 -0
  193. package/lib/components/input/uploadInput/uploadInput.stories.tsx +193 -0
  194. package/lib/components/navigation/bars/README.md +40 -0
  195. package/lib/components/navigation/bars/bars.stories.tsx +85 -0
  196. package/lib/components/navigation/bottomTab/README.md +53 -0
  197. package/lib/components/navigation/bottomTab/bottomTab.stories.tsx +32 -0
  198. package/lib/components/navigation/breadcrumb/README.md +48 -0
  199. package/lib/components/navigation/breadcrumb/breadcrumb.stories.tsx +27 -0
  200. package/lib/components/navigation/header/README.md +149 -0
  201. package/lib/components/navigation/header/header.stories.tsx +107 -0
  202. package/lib/components/navigation/leftNav/README.md +91 -0
  203. package/lib/components/navigation/leftNav/leftNav.stories.tsx +106 -0
  204. package/lib/components/navigation/tabs/README.md +75 -0
  205. package/lib/components/navigation/tabs/tabs.stories.tsx +60 -0
  206. package/lib/components/structure/column/README.md +40 -0
  207. package/lib/components/structure/column/column.stories.tsx +26 -0
  208. package/lib/components/structure/container/README.md +34 -0
  209. package/lib/components/structure/container/container.stories.tsx +19 -0
  210. package/lib/components/structure/link/README.md +55 -0
  211. package/lib/components/structure/link/link.stories.tsx +30 -0
  212. package/lib/components/structure/text/README.md +42 -0
  213. package/lib/components/structure/text/text.stories.tsx +39 -0
  214. package/lib/components/template/authPage/authPage.stories.tsx +68 -0
  215. package/lib/components/template/landingPage/landingPage.stories.tsx +288 -0
  216. package/lib/components/template/productListing/productListing.stories.tsx +297 -0
  217. package/lib/components/template/productOverview/productOverview.stories.tsx +194 -0
  218. package/lib/components/template/shoppingCart/shoppingCart.stories.tsx +252 -0
  219. package/lib/components/template/userHomePage/userHomePage.stories.tsx +605 -0
  220. package/lib/components/template/userRankingDashboard/userRankingDashboard.stories.tsx +481 -0
  221. package/lib/mcp/server.d.ts +2 -0
  222. package/lib/mcp/server.d.ts.map +1 -0
  223. package/lib/mcp/server.js +33 -0
  224. package/lib/mcp/server.js.map +1 -0
  225. package/lib/mcp/tools/getBackendComponent.d.ts +13 -0
  226. package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -0
  227. package/lib/mcp/tools/getBackendComponent.js +119 -0
  228. package/lib/mcp/tools/getBackendComponent.js.map +1 -0
  229. package/lib/mcp/tools/getComponent.d.ts +17 -0
  230. package/lib/mcp/tools/getComponent.d.ts.map +1 -0
  231. package/lib/mcp/tools/getComponent.js +118 -0
  232. package/lib/mcp/tools/getComponent.js.map +1 -0
  233. package/lib/mcp/tools/listComponents.d.ts +13 -0
  234. package/lib/mcp/tools/listComponents.d.ts.map +1 -0
  235. package/lib/mcp/tools/listComponents.js +113 -0
  236. package/lib/mcp/tools/listComponents.js.map +1 -0
  237. package/lib/mcp/tools/listTemplates.d.ts +13 -0
  238. package/lib/mcp/tools/listTemplates.d.ts.map +1 -0
  239. package/lib/mcp/tools/listTemplates.js +68 -0
  240. package/lib/mcp/tools/listTemplates.js.map +1 -0
  241. package/lib/mcp/tools/suggestTemplate.d.ts +17 -0
  242. package/lib/mcp/tools/suggestTemplate.d.ts.map +1 -0
  243. package/lib/mcp/tools/suggestTemplate.js +212 -0
  244. package/lib/mcp/tools/suggestTemplate.js.map +1 -0
  245. package/package.json +23 -0
@@ -0,0 +1,108 @@
1
+ # Select
2
+
3
+ <!-- STORY -->
4
+
5
+ <hr>
6
+
7
+ A versatile select component supporting single and multi select, multiple display types (dropdown, chips, radio view, modal), async search, dark mode, and custom action buttons.
8
+
9
+ ##### Import
10
+
11
+ ```js
12
+ import { Select, Option } from "blixify-ui-web/input/select";
13
+ ```
14
+
15
+ ##### Usage
16
+
17
+ Single select:
18
+
19
+ ```jsx
20
+ const [value, setValue] = useState("");
21
+
22
+ <Select
23
+ value={value}
24
+ label="Gender"
25
+ options={[
26
+ { key: "M", label: "Male" },
27
+ { key: "F", label: "Female" },
28
+ ]}
29
+ onChange={(v: string) => setValue(v)}
30
+ />;
31
+ ```
32
+
33
+ Multi select with tags:
34
+
35
+ ```jsx
36
+ const [value, setValue] = useState<string[]>([]);
37
+
38
+ <Select
39
+ label="Gender"
40
+ options={options}
41
+ value={value}
42
+ showTag={true}
43
+ onChange={(v: string[]) => setValue(v)}
44
+ />
45
+ ```
46
+
47
+ Async / database search:
48
+
49
+ ```jsx
50
+ <Select
51
+ value={value}
52
+ label="Search"
53
+ options={dbOptions}
54
+ onChange={(v) => setValue(v)}
55
+ onSearch={(search) => fetchOptions(search)}
56
+ />
57
+ ```
58
+
59
+ ##### Required props
60
+
61
+ | Name | Type | Description |
62
+ | --------- | -------------------- | ---------------------------------------------------------- |
63
+ | `value` | `string \| string[]` | Current value. Pass `string[]` to enable multi select mode |
64
+ | `label` | `string` | Field label |
65
+ | `options` | `Option[]` | List of selectable options |
66
+
67
+ ##### Optional props
68
+
69
+ | Name | Type | Default | Description |
70
+ | --------------------- | ---------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
71
+ | `type` | `"default" \| "button" \| "icon" \| "chips" \| "radioview" \| "modal"` | `"default"` | Display type. `"button"` shows option images, `"icon"` shows option icons, `"chips"` renders inline chip toggles, `"radioview"` renders a radio/checkbox list, `"modal"` opens a dual-panel selection modal |
72
+ | `id` | `string` | — | Field identifier |
73
+ | `placeholder` | `string` | — | Input placeholder text |
74
+ | `optional` | `boolean` | — | Skip required validation |
75
+ | `disabled` | `boolean` | — | Make the field read-only |
76
+ | `newValue` | `boolean` | — | Allow the user to type and add a value not in the options list |
77
+ | `autoFocus` | `boolean` | — | Focus the input on mount |
78
+ | `disableKeyboard` | `boolean` | `false` | Disable keyboard navigation in the dropdown |
79
+ | `showTag` | `boolean` | — | Show selected values as removable tags below the input (multi select only) |
80
+ | `closeOnClickOutside` | `boolean` | — | Keep the dropdown open until the user clicks outside. Multi select only |
81
+ | `mobileView` | `boolean` | — | Open a bottom-sheet modal on screens narrower than 768px instead of the inline dropdown |
82
+ | `portalDropdown` | `boolean` | — | Render the dropdown via a React portal (fixed position). Useful inside overflow-hidden containers |
83
+ | `staticDropdown` | `boolean` | — | Render the dropdown in static position (takes up space below the input) instead of absolute |
84
+ | `darkMode` | `boolean` | — | Enable dark mode styling |
85
+ | `subLabel` | `string` | — | Secondary label shown below the main label |
86
+ | `exclude` | `string[]` | — | Option keys to always exclude from the dropdown list |
87
+ | `additional` | `ReactElement` | — | Extra element always shown at the bottom of the dropdown |
88
+ | `customElement` | `ReactElement` | — | Extra element rendered next to the label |
89
+ | `labelExtra` | `ReactElement` | — | Extra element rendered inline with the label |
90
+ | `infoElement` | `ReactElement` | — | Info element rendered in the label area |
91
+ | `containerClassName` | `string` | — | Tailwind classes for the outer container |
92
+ | `selectClassName` | `string` | — | Tailwind classes for the select trigger element |
93
+ | `dropdownClassName` | `string` | — | Tailwind classes for the dropdown list |
94
+ | `imageClassName` | `string` | — | Tailwind classes for option images (used with `type="button"`) |
95
+ | `onChange` | `(value: string \| string[]) => void` | — | Called with the updated value when selection changes |
96
+ | `onSearch` | `(value: string) => void` | — | Called as the user types. Use to fetch options dynamically |
97
+ | `cellInput` | `CellInput` | — | Cell input config for use inside a Table component |
98
+
99
+ ##### Option
100
+
101
+ | Name | Type | Required | Description |
102
+ | ---------------- | -------------- | -------- | ------------------------------------------------------------- |
103
+ | `key` | `string` | yes | Unique option identifier — this is the value stored on select |
104
+ | `label` | `string` | yes | Display text |
105
+ | `secondaryLabel` | `string` | no | Secondary text shown below the label |
106
+ | `color` | `string` | no | Tailwind color key or hex string for the label text |
107
+ | `image` | `string` | no | Image URL shown when `type="button"` |
108
+ | `icon` | `ReactElement` | no | Icon element shown when `type="icon"` |
@@ -0,0 +1,286 @@
1
+ import { FolderPlusIcon, HomeIcon } from "@heroicons/react/24/outline";
2
+ import { storiesOf } from "@storybook/react";
3
+ import React, { useState } from "react";
4
+ import { Option, Select } from ".";
5
+ import { StorySection } from "../../storyUtils";
6
+ import README from "./README.md";
7
+
8
+ const stories = storiesOf("Input", module);
9
+
10
+ stories.addParameters({
11
+ readme: {
12
+ content: README,
13
+ },
14
+ });
15
+
16
+ const genderOptions: Option[] = [
17
+ {
18
+ key: "M",
19
+ label: "Male",
20
+ secondaryLabel: "Secondary Label",
21
+ image:
22
+ "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
23
+ icon: <HomeIcon className="h-6 w-6 mr-3 group-hover:text-white" />,
24
+ },
25
+ {
26
+ key: "F",
27
+ label: "Female",
28
+ secondaryLabel: "Secondary Label",
29
+ image:
30
+ "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
31
+ icon: <FolderPlusIcon className="h-6 w-6 mr-3 group-hover:text-white" />,
32
+ },
33
+ {
34
+ key: "F2",
35
+ label: "Fluid",
36
+ secondaryLabel: "Secondary Label",
37
+ image:
38
+ "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
39
+ icon: <HomeIcon className="h-6 w-6 mr-3 group-hover:text-white" />,
40
+ },
41
+ {
42
+ key: "notToSay",
43
+ label: "Prefer Not To Say",
44
+ secondaryLabel: "Secondary Label",
45
+ image:
46
+ "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
47
+ icon: <FolderPlusIcon className="h-6 w-6 mr-3 group-hover:text-white" />,
48
+ },
49
+ {
50
+ key: "others",
51
+ label: "Others",
52
+ secondaryLabel: "Secondary Label",
53
+ image:
54
+ "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80",
55
+ icon: <FolderPlusIcon className="h-6 w-6 mr-3 group-hover:text-white" />,
56
+ },
57
+ ];
58
+
59
+ stories.add("Select", () => {
60
+ const [value, setValue] = useState("");
61
+ const [multiValue, setMultiValue] = useState<string[]>(["M"]);
62
+ const [dbValue, setDBValue] = useState("");
63
+ const [dbOptions, setDBOptions] = useState<Option[]>([
64
+ { key: "M", label: "Male", secondaryLabel: "Secondary Label" },
65
+ ]);
66
+
67
+ const handleOptionSearch = (search: string) => {
68
+ if (search.includes("M")) {
69
+ setDBOptions([
70
+ { key: "M", label: "Male", secondaryLabel: "Secondary Label" },
71
+ ]);
72
+ } else if (search.includes("F")) {
73
+ setDBOptions([
74
+ { key: "F", label: "Female", secondaryLabel: "Secondary Label" },
75
+ ]);
76
+ }
77
+ };
78
+
79
+ return (
80
+ <>
81
+ <StorySection
82
+ title="Single & Multi Select"
83
+ description="Pass a string value for single select, or string[] for multi select. showTag=true renders selected values as removable tags below the input."
84
+ >
85
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-2 w-full">
86
+ <Select
87
+ value={value}
88
+ label="Single Select"
89
+ options={genderOptions}
90
+ onChange={(v: string) => setValue(v)}
91
+ />
92
+ <Select
93
+ label="Multi Select"
94
+ options={genderOptions}
95
+ value={multiValue}
96
+ showTag={true}
97
+ onChange={(v: string[]) => setMultiValue(v)}
98
+ />
99
+ </div>
100
+ </StorySection>
101
+
102
+ <StorySection
103
+ title="New Value"
104
+ description="newValue=true lets the user type and add a value that isn't in the options list."
105
+ >
106
+ <div className="w-full md:w-1/2">
107
+ <Select
108
+ value={value}
109
+ label="Single Select with New Value"
110
+ options={genderOptions}
111
+ onChange={(v: string) => setValue(v)}
112
+ newValue
113
+ />
114
+ </div>
115
+ </StorySection>
116
+
117
+ <StorySection
118
+ title="Icon & Image Types"
119
+ description='type="icon" shows the option icon in the trigger. type="button" shows the option image. imageClassName controls the image size and shape.'
120
+ >
121
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-2 w-full">
122
+ <Select
123
+ value={value}
124
+ label="With Icon"
125
+ type="icon"
126
+ options={genderOptions}
127
+ onChange={(v: string) => setValue(v)}
128
+ />
129
+ <Select
130
+ value={value}
131
+ label="With Image"
132
+ type="button"
133
+ imageClassName="h-6 w-6 mr-3 rounded-full"
134
+ options={genderOptions}
135
+ onChange={(v: string) => setValue(v)}
136
+ />
137
+ </div>
138
+ </StorySection>
139
+
140
+ <StorySection
141
+ title="Chips"
142
+ description='type="chips" renders options as inline chip toggles instead of a dropdown. Works for both single and multi select.'
143
+ >
144
+ <div className="w-full space-y-4">
145
+ <Select
146
+ value={value}
147
+ label="Single Select (Chips)"
148
+ options={genderOptions}
149
+ type="chips"
150
+ onChange={(v: string) => setValue(v)}
151
+ />
152
+ <Select
153
+ label="Multi Select (Chips)"
154
+ options={genderOptions}
155
+ value={multiValue}
156
+ type="chips"
157
+ onChange={(v: string[]) => setMultiValue(v)}
158
+ />
159
+ <Select
160
+ label="Disabled (Chips)"
161
+ options={genderOptions}
162
+ value={multiValue}
163
+ type="chips"
164
+ disabled
165
+ onChange={(v: string[]) => setMultiValue(v)}
166
+ />
167
+ </div>
168
+ </StorySection>
169
+
170
+ <StorySection
171
+ title="Radio View"
172
+ description='type="radioview" renders options as a radio/checkbox list. Works for both single and multi select.'
173
+ >
174
+ <div className="w-full space-y-4">
175
+ <Select
176
+ value={value}
177
+ label="Single Select (Radio View)"
178
+ options={genderOptions}
179
+ type="radioview"
180
+ onChange={(v: string) => setValue(v)}
181
+ />
182
+ <Select
183
+ label="Multi Select (Radio View)"
184
+ options={genderOptions}
185
+ value={multiValue}
186
+ type="radioview"
187
+ onChange={(v: string[]) => setMultiValue(v)}
188
+ />
189
+ <Select
190
+ label="Disabled (Radio View)"
191
+ options={genderOptions}
192
+ value={multiValue}
193
+ type="radioview"
194
+ disabled
195
+ onChange={(v: string[]) => setMultiValue(v)}
196
+ />
197
+ </div>
198
+ </StorySection>
199
+
200
+ <StorySection
201
+ title="Modal Type"
202
+ description='type="modal" opens a dual-panel modal for moving options between available and selected lists. Useful for large option sets.'
203
+ >
204
+ <div className="w-full md:w-1/2">
205
+ <Select
206
+ label="Modal Select"
207
+ options={genderOptions}
208
+ value={multiValue}
209
+ type="modal"
210
+ onChange={(v: string[]) => setMultiValue(v)}
211
+ />
212
+ </div>
213
+ </StorySection>
214
+
215
+ <StorySection
216
+ title="Mobile View"
217
+ description="mobileView=true opens a bottom-sheet modal on screens narrower than 768px instead of the inline dropdown."
218
+ >
219
+ <div className="w-full md:w-1/2">
220
+ <Select
221
+ value={value}
222
+ label="Mobile View"
223
+ options={genderOptions}
224
+ mobileView
225
+ onChange={(v: string) => setValue(v)}
226
+ />
227
+ </div>
228
+ </StorySection>
229
+
230
+ <StorySection
231
+ title="Database / Async Search"
232
+ description="Pass onSearch to fetch options dynamically as the user types. Update the options prop with the search results."
233
+ >
234
+ <div className="w-full md:w-1/2">
235
+ <Select
236
+ value={dbValue}
237
+ label="Database Select"
238
+ options={dbOptions}
239
+ onChange={(v: string) => setDBValue(v)}
240
+ onSearch={handleOptionSearch}
241
+ />
242
+ </div>
243
+ </StorySection>
244
+
245
+ <StorySection
246
+ title="Dark Mode"
247
+ description="Pass darkMode=true to switch to a dark-themed select."
248
+ dark
249
+ >
250
+ <div className="w-full md:w-1/2">
251
+ <Select
252
+ value={value}
253
+ label="Single Select"
254
+ type="icon"
255
+ options={genderOptions}
256
+ onChange={(v: string) => setValue(v)}
257
+ darkMode={true}
258
+ />
259
+ </div>
260
+ </StorySection>
261
+
262
+ <StorySection
263
+ title="Disabled"
264
+ description="disabled=true makes the select read-only."
265
+ >
266
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-2 w-full">
267
+ <Select
268
+ value={value}
269
+ label="Disabled Single"
270
+ options={genderOptions}
271
+ disabled={true}
272
+ onChange={(v: string) => setValue(v)}
273
+ />
274
+ <Select
275
+ label="Disabled Multi"
276
+ options={genderOptions}
277
+ value={multiValue}
278
+ disabled={true}
279
+ showTag={true}
280
+ onChange={(v: string[]) => setMultiValue(v)}
281
+ />
282
+ </div>
283
+ </StorySection>
284
+ </>
285
+ );
286
+ });
@@ -0,0 +1,106 @@
1
+ # Signature
2
+
3
+ <!-- STORY -->
4
+
5
+ <hr>
6
+
7
+ E-signature component with a resizable canvas, optional pre-loaded image, clear/reset controls, and form validation support.
8
+
9
+ ### Import
10
+
11
+ ```js
12
+ import { Signature } from "blixify-ui-web/input/signature";
13
+ ```
14
+
15
+ ### Usage
16
+
17
+ ```jsx
18
+ const signatureRef = useRef(null);
19
+ const [signing, setSigning] = useState(false);
20
+ const [preview, setPreview] = useState("");
21
+
22
+ // Give the parent a fixed height — the canvas fills it
23
+ <div className="h-72">
24
+ <Signature
25
+ id="signature"
26
+ ref={signatureRef}
27
+ label="Signature"
28
+ signing={signing}
29
+ penColor="black"
30
+ signatureClear={true}
31
+ onChange={setSigning}
32
+ onSubmit={(_, dataURL) => setPreview(dataURL ?? "")}
33
+ />
34
+ </div>
35
+ <Button text="Submit" onClick={() => signatureRef.current?.handleSubmit()} />
36
+ ```
37
+
38
+ ### Validation via ref
39
+
40
+ `handleSubmit()` returns a `Promise<boolean>`. It passes when:
41
+
42
+ - `optional` is `true`, or
43
+ - `dataURL` is set (existing signature from server), or
44
+ - the user has drawn on the canvas (`signing` is `true`)
45
+
46
+ ### Pre-loading an existing signature
47
+
48
+ ```jsx
49
+ <div className="h-72">
50
+ <Signature
51
+ id="signature"
52
+ ref={signatureRef}
53
+ dataURL="https://example.com/signature.png"
54
+ signing={signing}
55
+ label="Signature"
56
+ signatureClear={true}
57
+ onChange={setSigning}
58
+ onSubmit={(_, dataURL) => setPreview(dataURL ?? "")}
59
+ />
60
+ </div>
61
+ ```
62
+
63
+ The image at `dataURL` must have `Access-Control-Allow-Origin: *`. A Reset button appears automatically when `dataURL` is set.
64
+
65
+ ### Inside a Modal
66
+
67
+ Force remount with a `key` prop when the modal opens so the canvas measures its container correctly:
68
+
69
+ ```jsx
70
+ const [modalKey, setModalKey] = useState(0);
71
+
72
+ <Button text="Open" onClick={() => { setIsOpen(true); setModalKey(k => k + 1); }} />
73
+ <Modal open={isOpen} ...>
74
+ <div className="h-72">
75
+ <Signature key={modalKey} id="sig" ... />
76
+ </div>
77
+ </Modal>
78
+ ```
79
+
80
+ ### Required props
81
+
82
+ | Name | Type | Description |
83
+ | --------- | --------- | ------------------------------------------- |
84
+ | `id` | `string` | HTML id for the component |
85
+ | `label` | `string` | Label displayed above the canvas |
86
+ | `signing` | `boolean` | Tracks whether the canvas has been drawn on |
87
+
88
+ ### Optional props
89
+
90
+ | Name | Type | Default | Description |
91
+ | -------------------------- | ----------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------- |
92
+ | `dataURL` | `string` | — | URL of an existing signature image to pre-load. Must allow CORS (`Access-Control-Allow-Origin: *`) |
93
+ | `subLabel` | `string` | — | Secondary label shown below the main label |
94
+ | `labelExtra` | `ReactElement` | — | Extra element rendered inline with the label |
95
+ | `infoElement` | `ReactElement` | — | Content shown in an InfoWindow tooltip next to the label |
96
+ | `customElement` | `ReactElement` | — | Custom element rendered in the label row (right side) |
97
+ | `optional` | `boolean` | `false` | Skips validation when `true` |
98
+ | `darkMode` | `boolean` | `false` | Switches label colours for dark backgrounds |
99
+ | `penColor` | `string` | `"black"` | Ink colour for the signature canvas |
100
+ | `signatureClear` | `boolean` | `false` | Shows a Clear button to wipe the canvas |
101
+ | `description` | `string` | — | Text shown above the pad. Wrap in `*asterisks*` for bold. Blank lines create paragraph spacing. |
102
+ | `className` | `tailwind class` | — | Class applied to the outer container |
103
+ | `containerClassName` | `tailwind class` | — | Class applied to the component wrapper |
104
+ | `canvasContainerClassName` | `tailwind class` | — | Class applied to the canvas border/shadow container |
105
+ | `onChange` | `(signing: boolean) => void` | — | Called when the user starts drawing (`true`) or the canvas is cleared (`false`) |
106
+ | `onSubmit` | `(result: any, dataURL?: string) => void` | — | Called on successful `handleSubmit`. `dataURL` is a base64 PNG string of the drawn signature, or `""` if cleared |