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.
- package/README.md +5 -0
- package/lib/components/action/button/README.md +75 -0
- package/lib/components/action/button/button.stories.tsx +138 -0
- package/lib/components/action/buttonGroup/README.md +79 -0
- package/lib/components/action/buttonGroup/buttonGroup.stories.tsx +104 -0
- package/lib/components/action/iconButton/README.md +39 -0
- package/lib/components/action/iconButton/iconButton.stories.tsx +22 -0
- package/lib/components/action/radioList/README.md +98 -0
- package/lib/components/action/radioList/radioList.stories.tsx +181 -0
- package/lib/components/action/slider/README.md +86 -0
- package/lib/components/action/slider/slider.stories.tsx +133 -0
- package/lib/components/action/textButton/README.md +34 -0
- package/lib/components/action/textButton/textButton.stories.tsx +16 -0
- package/lib/components/action/toggle/README.md +39 -0
- package/lib/components/action/toggle/toggle.stories.tsx +23 -0
- package/lib/components/advanced/collapse/README.md +106 -0
- package/lib/components/advanced/collapse/collapse.stories.tsx +165 -0
- package/lib/components/advanced/infoWindow/README.md +69 -0
- package/lib/components/advanced/infoWindow/infoWindow.stories.tsx +112 -0
- package/lib/components/advanced/popUp/README.md +95 -0
- package/lib/components/advanced/popUp/popUp.stories.tsx +189 -0
- package/lib/components/auth/bareSignIn/README.md +78 -0
- package/lib/components/auth/bareSignIn/bareSignIn.stories.tsx +141 -0
- package/lib/components/auth/bareSignUp/README.md +130 -0
- package/lib/components/auth/bareSignUp/bareSignUp.stories.tsx +159 -0
- package/lib/components/auth/signIn/README.md +53 -0
- package/lib/components/auth/signIn/signIn.stories.tsx +120 -0
- package/lib/components/auth/signUp/README.md +136 -0
- package/lib/components/auth/signUp/signUp.stories.tsx +193 -0
- package/lib/components/chart/README.md +13 -0
- package/lib/components/chart/areaChart/README.md +133 -0
- package/lib/components/chart/areaChart/areaChart.stories.tsx +199 -0
- package/lib/components/chart/barChart/README.md +193 -0
- package/lib/components/chart/barChart/barChart.stories.tsx +318 -0
- package/lib/components/chart/boxPlotChart/README.md +124 -0
- package/lib/components/chart/boxPlotChart/boxPlotChart.stories.tsx +104 -0
- package/lib/components/chart/bubbleChart/README.md +166 -0
- package/lib/components/chart/bubbleChart/bubbleChart.stories.tsx +144 -0
- package/lib/components/chart/card/README.md +107 -0
- package/lib/components/chart/card/card.stories.tsx +89 -0
- package/lib/components/chart/ganttChart/README.md +142 -0
- package/lib/components/chart/ganttChart/ganttChart.stories.tsx +138 -0
- package/lib/components/chart/heatmapChart/README.md +125 -0
- package/lib/components/chart/heatmapChart/heatmapChart.stories.tsx +106 -0
- package/lib/components/chart/lineChart/README.md +140 -0
- package/lib/components/chart/lineChart/lineChart.stories.tsx +152 -0
- package/lib/components/chart/pieChart/README.md +117 -0
- package/lib/components/chart/pieChart/pieChart.stories.tsx +180 -0
- package/lib/components/chart/polarAreaChart/README.md +126 -0
- package/lib/components/chart/polarAreaChart/polarAreaChart.stories.tsx +106 -0
- package/lib/components/chart/radarChart/README.md +57 -0
- package/lib/components/chart/radarChart/radarChart.stories.tsx +36 -0
- package/lib/components/chart/radialBar/README.md +152 -0
- package/lib/components/chart/radialBar/radialChart.stories.tsx +136 -0
- package/lib/components/chart/rangeBarChart/README.md +323 -0
- package/lib/components/chart/rangeBarChart/rangeBarChart.stories.tsx +208 -0
- package/lib/components/chart/statsCard/README.md +97 -0
- package/lib/components/chart/statsCard/statsCard.stories.tsx +183 -0
- package/lib/components/chart/treemapChart/README.md +142 -0
- package/lib/components/chart/treemapChart/treemapChart.stories.tsx +122 -0
- package/lib/components/chat/chatAnchor/README.md +113 -0
- package/lib/components/chat/chatAnchor/chatAnchor.stories.tsx +156 -0
- package/lib/components/chat/chatBase/README.md +223 -0
- package/lib/components/chat/chatBase/chatBase.stories.tsx +306 -0
- package/lib/components/chat/chatDashboard/README.md +161 -0
- package/lib/components/chat/chatDashboard/chatDashboard.stories.tsx +154 -0
- package/lib/components/data/dataGraph/README.md +13 -0
- package/lib/components/data/dataGraph/dataGraph.stories.tsx +84 -0
- package/lib/components/data/dataReference/README.md +62 -0
- package/lib/components/data/dataReference/dataReference.stories.tsx +53 -0
- package/lib/components/data/dataTemplate/README.md +903 -0
- package/lib/components/data/dataTemplate/dataModule.stories.tsx +196 -0
- package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +337 -0
- package/lib/components/data/dataWrapper/README.md +1077 -0
- package/lib/components/data/dataWrapper/dataWrapper.stories.tsx +831 -0
- package/lib/components/data/queryForm/README.md +56 -0
- package/lib/components/data/queryForm/queryForm.stories.tsx +85 -0
- package/lib/components/data/readQuery/README.md +282 -0
- package/lib/components/data/readQuery/readQuery.stories.tsx +256 -0
- package/lib/components/data/readQueryHoc/README.md +89 -0
- package/lib/components/data/readQueryHoc/readQueryHoc.stories.tsx +33 -0
- package/lib/components/data/writeQuery/README.md +178 -0
- package/lib/components/data/writeQuery/writeQuery.stories.tsx +209 -0
- package/lib/components/design/actionSection/README.md +47 -0
- package/lib/components/design/actionSection/actionSection.stories.tsx +74 -0
- package/lib/components/design/banner/README.md +43 -0
- package/lib/components/design/banner/banner.stories.tsx +34 -0
- package/lib/components/design/bannerAction/README.md +44 -0
- package/lib/components/design/bannerAction/bannerAction.stories.tsx +25 -0
- package/lib/components/design/blogSection/README.md +111 -0
- package/lib/components/design/blogSection/blogSection.stories.tsx +72 -0
- package/lib/components/design/carouselSection/README.md +82 -0
- package/lib/components/design/carouselSection/carouselSection.stories.tsx +52 -0
- package/lib/components/design/designList/README.md +60 -0
- package/lib/components/design/designList/designList.stories.tsx +44 -0
- package/lib/components/design/faq/README.md +121 -0
- package/lib/components/design/faq/faq.stories.tsx +103 -0
- package/lib/components/design/fileGrid/README.md +87 -0
- package/lib/components/design/fileGrid/fileGrid.stories.tsx +110 -0
- package/lib/components/design/fileViewer/README.md +40 -0
- package/lib/components/design/fileViewer/fileViewer.stories.tsx +28 -0
- package/lib/components/design/footerSection/README.md +62 -0
- package/lib/components/design/footerSection/footerSection.stories.tsx +84 -0
- package/lib/components/design/googleReview/README.md +45 -0
- package/lib/components/design/googleReview/googleReview.stories.tsx +33 -0
- package/lib/components/design/heroSection/README.md +48 -0
- package/lib/components/design/heroSection/heroSection.stories.tsx +85 -0
- package/lib/components/design/iconList/README.md +60 -0
- package/lib/components/design/iconList/iconList.stories.tsx +41 -0
- package/lib/components/design/imageGallery/README.md +56 -0
- package/lib/components/design/imageGallery/imageGallery.stories.tsx +45 -0
- package/lib/components/design/imageZoom/README.md +47 -0
- package/lib/components/design/imageZoom/imageZoom.stories.tsx +30 -0
- package/lib/components/design/leftContent/README.md +47 -0
- package/lib/components/design/leftContent/leftContent.stories.tsx +32 -0
- package/lib/components/design/logoCloud/README.md +42 -0
- package/lib/components/design/logoCloud/logoCloud.stories.tsx +44 -0
- package/lib/components/design/onboarding/README.md +100 -0
- package/lib/components/design/onboarding/onboarding.stories.tsx +113 -0
- package/lib/components/design/pricing/README.md +112 -0
- package/lib/components/design/pricing/pricing.stories.tsx +86 -0
- package/lib/components/design/rightContent/README.md +47 -0
- package/lib/components/design/rightContent/rightContent.stories.tsx +32 -0
- package/lib/components/design/sectionList/README.md +51 -0
- package/lib/components/design/sectionList/sectionList.stories.tsx +35 -0
- package/lib/components/design/teams/README.md +62 -0
- package/lib/components/design/teams/teams.stories.tsx +61 -0
- package/lib/components/display/alert/README.md +82 -0
- package/lib/components/display/alert/alert.stories.tsx +71 -0
- package/lib/components/display/calendar/README.md +113 -0
- package/lib/components/display/calendar/calendar.stories.tsx +159 -0
- package/lib/components/display/clipboard/README.md +36 -0
- package/lib/components/display/clipboard/clipboard.stories.tsx +32 -0
- package/lib/components/display/detailList/README.md +61 -0
- package/lib/components/display/detailList/detailList.stories.tsx +131 -0
- package/lib/components/display/drawer/README.md +74 -0
- package/lib/components/display/drawer/drawer.stories.tsx +66 -0
- package/lib/components/display/emptyState/README.md +38 -0
- package/lib/components/display/emptyState/emptyState.stories.tsx +22 -0
- package/lib/components/display/feeds/README.md +80 -0
- package/lib/components/display/feeds/feeds.stories.tsx +75 -0
- package/lib/components/display/flexTable/README.md +160 -0
- package/lib/components/display/flexTable/flexTable.stories.tsx +313 -0
- package/lib/components/display/grid/README.md +121 -0
- package/lib/components/display/grid/grid.stories.tsx +234 -0
- package/lib/components/display/kanban/README.md +78 -0
- package/lib/components/display/kanban/kanban.stories.tsx +133 -0
- package/lib/components/display/list/README.md +109 -0
- package/lib/components/display/list/list.stories.tsx +188 -0
- package/lib/components/display/loading/README.md +25 -0
- package/lib/components/display/loading/loading.stories.tsx +15 -0
- package/lib/components/display/mapView/README.md +99 -0
- package/lib/components/display/mapView/mapView.stories.tsx +225 -0
- package/lib/components/display/modal/README.md +43 -0
- package/lib/components/display/modal/modal.stories.tsx +81 -0
- package/lib/components/display/notification/README.md +43 -0
- package/lib/components/display/notification/notification.stories.tsx +30 -0
- package/lib/components/display/progress/README.md +25 -0
- package/lib/components/display/progress/progress.stories.tsx +15 -0
- package/lib/components/display/stepper/README.md +96 -0
- package/lib/components/display/stepper/stepper.stories.tsx +175 -0
- package/lib/components/display/table/README.md +176 -0
- package/lib/components/display/table/table.stories.tsx +330 -0
- package/lib/components/display/tag/README.md +74 -0
- package/lib/components/display/tag/tag.stories.tsx +79 -0
- package/lib/components/input/address/README.md +132 -0
- package/lib/components/input/address/address.stories.tsx +147 -0
- package/lib/components/input/canvas/README.md +131 -0
- package/lib/components/input/canvas/canvas.stories.tsx +165 -0
- package/lib/components/input/checkbox/README.md +61 -0
- package/lib/components/input/checkbox/checkbox.stories.tsx +30 -0
- package/lib/components/input/datePicker/README.md +124 -0
- package/lib/components/input/datePicker/datePicker.stories.tsx +197 -0
- package/lib/components/input/form/README.md +55 -0
- package/lib/components/input/form/form.stories.tsx +143 -0
- package/lib/components/input/markdown/README.md +146 -0
- package/lib/components/input/markdown/markdown.stories.tsx +40 -0
- package/lib/components/input/monthYearPicker/README.md +69 -0
- package/lib/components/input/monthYearPicker/monthYearPicker.stories.tsx +47 -0
- package/lib/components/input/netPromoterScore/README.md +52 -0
- package/lib/components/input/netPromoterScore/netPromoterScore.stories.tsx +30 -0
- package/lib/components/input/rating/README.md +51 -0
- package/lib/components/input/rating/rating.stories.tsx +30 -0
- package/lib/components/input/select/README.md +108 -0
- package/lib/components/input/select/select.stories.tsx +286 -0
- package/lib/components/input/signature/README.md +106 -0
- package/lib/components/input/signature/signature.stories.tsx +188 -0
- package/lib/components/input/textArea/README.md +55 -0
- package/lib/components/input/textArea/textArea.stories.tsx +30 -0
- package/lib/components/input/textInput/README.md +81 -0
- package/lib/components/input/textInput/textinput.stories.tsx +231 -0
- package/lib/components/input/uploadInput/README.md +134 -0
- package/lib/components/input/uploadInput/uploadInput.stories.tsx +193 -0
- package/lib/components/navigation/bars/README.md +40 -0
- package/lib/components/navigation/bars/bars.stories.tsx +85 -0
- package/lib/components/navigation/bottomTab/README.md +53 -0
- package/lib/components/navigation/bottomTab/bottomTab.stories.tsx +32 -0
- package/lib/components/navigation/breadcrumb/README.md +48 -0
- package/lib/components/navigation/breadcrumb/breadcrumb.stories.tsx +27 -0
- package/lib/components/navigation/header/README.md +149 -0
- package/lib/components/navigation/header/header.stories.tsx +107 -0
- package/lib/components/navigation/leftNav/README.md +91 -0
- package/lib/components/navigation/leftNav/leftNav.stories.tsx +106 -0
- package/lib/components/navigation/tabs/README.md +75 -0
- package/lib/components/navigation/tabs/tabs.stories.tsx +60 -0
- package/lib/components/structure/column/README.md +40 -0
- package/lib/components/structure/column/column.stories.tsx +26 -0
- package/lib/components/structure/container/README.md +34 -0
- package/lib/components/structure/container/container.stories.tsx +19 -0
- package/lib/components/structure/link/README.md +55 -0
- package/lib/components/structure/link/link.stories.tsx +30 -0
- package/lib/components/structure/text/README.md +42 -0
- package/lib/components/structure/text/text.stories.tsx +39 -0
- package/lib/components/template/authPage/authPage.stories.tsx +68 -0
- package/lib/components/template/landingPage/landingPage.stories.tsx +288 -0
- package/lib/components/template/productListing/productListing.stories.tsx +297 -0
- package/lib/components/template/productOverview/productOverview.stories.tsx +194 -0
- package/lib/components/template/shoppingCart/shoppingCart.stories.tsx +252 -0
- package/lib/components/template/userHomePage/userHomePage.stories.tsx +605 -0
- package/lib/components/template/userRankingDashboard/userRankingDashboard.stories.tsx +481 -0
- package/lib/mcp/server.d.ts +2 -0
- package/lib/mcp/server.d.ts.map +1 -0
- package/lib/mcp/server.js +33 -0
- package/lib/mcp/server.js.map +1 -0
- package/lib/mcp/tools/getBackendComponent.d.ts +13 -0
- package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -0
- package/lib/mcp/tools/getBackendComponent.js +119 -0
- package/lib/mcp/tools/getBackendComponent.js.map +1 -0
- package/lib/mcp/tools/getComponent.d.ts +17 -0
- package/lib/mcp/tools/getComponent.d.ts.map +1 -0
- package/lib/mcp/tools/getComponent.js +118 -0
- package/lib/mcp/tools/getComponent.js.map +1 -0
- package/lib/mcp/tools/listComponents.d.ts +13 -0
- package/lib/mcp/tools/listComponents.d.ts.map +1 -0
- package/lib/mcp/tools/listComponents.js +113 -0
- package/lib/mcp/tools/listComponents.js.map +1 -0
- package/lib/mcp/tools/listTemplates.d.ts +13 -0
- package/lib/mcp/tools/listTemplates.d.ts.map +1 -0
- package/lib/mcp/tools/listTemplates.js +68 -0
- package/lib/mcp/tools/listTemplates.js.map +1 -0
- package/lib/mcp/tools/suggestTemplate.d.ts +17 -0
- package/lib/mcp/tools/suggestTemplate.d.ts.map +1 -0
- package/lib/mcp/tools/suggestTemplate.js +212 -0
- package/lib/mcp/tools/suggestTemplate.js.map +1 -0
- 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 |
|