blixify-ui-web-mcp 0.1.71 → 0.1.75
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/lib/components/chart/barChart/README.md +2 -0
- package/lib/components/chart/barChart/barChart.stories.tsx +86 -3
- package/lib/components/chart/pieChart/README.md +3 -1
- package/lib/components/chart/pieChart/pieChart.stories.tsx +18 -1
- package/lib/components/data/dataGraph/README.md +18 -1
- package/lib/components/data/dataTemplate/README.md +72 -4
- package/lib/components/data/dataTemplate/activityModal.stories.tsx +52 -0
- package/lib/components/data/dataTemplate/dataTemplate.groupedBoard.stories.tsx +259 -0
- package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +162 -0
- package/lib/components/data/dataWrapper/README.md +45 -3
- package/lib/components/data/flexFilter/flexFilterRelated.stories.tsx +182 -0
- package/lib/components/data/readQuery/README.md +8 -8
- package/lib/components/display/drawer/README.md +1 -1
- package/lib/components/display/modal/README.md +1 -0
- package/lib/components/input/textInput/README.md +30 -30
- package/lib/components/input/textInput/textinput.stories.tsx +30 -0
- package/lib/components/navigation/leftNav/README.md +2 -1
- package/lib/components/navigation/leftNav/leftNav.stories.tsx +61 -0
- package/package.json +1 -1
|
@@ -242,14 +242,14 @@ const res = await query.call({
|
|
|
242
242
|
|
|
243
243
|
## Query
|
|
244
244
|
|
|
245
|
-
| Param | Type | Description
|
|
246
|
-
| ---------------- | ----------------------------------------------------------------------------------------- |
|
|
247
|
-
| `type` | `search \| = \| != \| > \| < \| >< \| in \| !in \| exists \| elemMatch \| >size \| <size` | Operator
|
|
248
|
-
| `value` | `any` | Filter value (array for `><` and `in`)
|
|
249
|
-
| `queryId` | `string` | Field name
|
|
250
|
-
| `searchIds` | `string[]` | Fields to search across
|
|
251
|
-
| `orQuery` | `boolean` | Use OR instead of AND
|
|
252
|
-
| `orQueryGroupId` | `string` |
|
|
245
|
+
| Param | Type | Description | Optional |
|
|
246
|
+
| ---------------- | ----------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------ |
|
|
247
|
+
| `type` | `search \| = \| != \| > \| < \| >< \| in \| !in \| exists \| elemMatch \| >size \| <size` | Operator | |
|
|
248
|
+
| `value` | `any` | Filter value (array for `><` and `in`) | |
|
|
249
|
+
| `queryId` | `string` | Field name | Required except `search` |
|
|
250
|
+
| `searchIds` | `string[]` | Fields to search across | Required for `search` |
|
|
251
|
+
| `orQuery` | `boolean` | Use OR instead of AND | ✓ |
|
|
252
|
+
| `orQueryGroupId` | `string` | AND inside a block, OR between blocks | ✓ |
|
|
253
253
|
|
|
254
254
|
## Aggregate
|
|
255
255
|
|
|
@@ -103,5 +103,5 @@ Two behaviours differ in controlled mode:
|
|
|
103
103
|
| `desc` | `string` | - | The description text displayed below the title |
|
|
104
104
|
| `anchor` | `"bottom" \| "right" \| "responsive"` | `right` | `responsive` uses a right panel above the `sm` breakpoint (640px) and a bottom sheet below it, where a right panel covers almost the whole viewport |
|
|
105
105
|
| `maxWidth` | `"lg" \| "xl" \| "2xl" \| "3xl" \| "4xl" \| "5xl" \| "6xl" \| "7xl"` | `lg` | Maximum width of the drawer (right anchor only) |
|
|
106
|
-
| `maxHeight` | `"50" \| "75" \| "100"` | `100` | Height of the drawer as a viewport height percentage (bottom anchor only) |
|
|
106
|
+
| `maxHeight` | `"50" \| "75" \| "90" \| "100"` | `100` | Height of the drawer as a viewport height percentage (bottom anchor only) |
|
|
107
107
|
| `expandable` | `boolean` | - | Shows a maximize toggle in the header that grows the panel to the full viewport (width on the right anchor, height on the bottom sheet) and back. Expansion resets when the drawer closes |
|
|
@@ -44,3 +44,4 @@ import { Overlay } from "blixify-ui-web/components/display/overlay";
|
|
|
44
44
|
| `bgColor` | `string` | `bg-white` | Tailwind background class for the panel in light mode |
|
|
45
45
|
| `darkMode` | `boolean` | `false` | Switches the panel, text and icons to the dark palette |
|
|
46
46
|
| `darkModeBg` | `string` | `bg-gray-900` | Tailwind background class for the panel when `darkMode` is on |
|
|
47
|
+
| `zIndex` | `string` | `z-40` | Tailwind z-index class for the dialog. Pass a higher one for a modal opened from a layer drawn above z-40, such as the activity drawer (z-50) |
|
|
@@ -50,34 +50,34 @@ const ref = useRef(null);
|
|
|
50
50
|
|
|
51
51
|
### Optional props
|
|
52
52
|
|
|
53
|
-
| Name | Type | Default | Description
|
|
54
|
-
| ----------------------- | ------------------ | ---------- |
|
|
55
|
-
| `id` | `string` | — | HTML id attribute
|
|
56
|
-
| `subLabel` | `string` | — | Secondary label shown below the main label
|
|
53
|
+
| Name | Type | Default | Description |
|
|
54
|
+
| ----------------------- | ------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
55
|
+
| `id` | `string` | — | HTML id attribute |
|
|
56
|
+
| `subLabel` | `string` | — | Secondary label shown below the main label |
|
|
57
57
|
| `size` | `string` | — | `"small"` (px-3 py-2), `"mini"` (p-2) or `"xs"`; default is standard (px-5 py-3). `"xs"` looks 12px everywhere: on phones it keeps 16px text and draws the field at 75%, so iOS Safari does not zoom on focus; from `sm` up it is a plain 12px field. Give it a width through `containerClassName` when it sits in a row |
|
|
58
|
-
| `enterKeyHint` | `string` | — | Label for a phone keyboard's enter key, e.g. `"done"`, `"search"`, `"go"`
|
|
59
|
-
| `onKeyDown` | `(e) => void` | — | Passed to the `<input>` — e.g. Enter to commit, Escape to cancel
|
|
60
|
-
| `labelExtra` | `ReactElement` | — | Extra element rendered inline with the label
|
|
61
|
-
| `infoElement` | `ReactElement` | — | Content shown in an InfoWindow tooltip next to the label
|
|
62
|
-
| `customElement` | `ReactElement` | — | Custom element rendered to the right of the label row
|
|
63
|
-
| `pattern` | `string` | — | Regex string applied on submit (overrides type-based validation)
|
|
64
|
-
| `customErrMsg` | `string` | — | Overrides the default validation error message
|
|
65
|
-
| `minNumber` | `number` | — | Minimum value (type `"number"` only)
|
|
66
|
-
| `maxNumber` | `number` | — | Maximum value (type `"number"` only)
|
|
67
|
-
| `maxLength` | `number` | — | Max character length
|
|
68
|
-
| `optional` | `boolean` | `false` | Skips validation when `true`
|
|
69
|
-
| `disabled` | `boolean` | `false` | Disables the input
|
|
70
|
-
| `autoFocus` | `boolean` | `false` | Focuses the input on mount
|
|
71
|
-
| `autoComplete` | `"on"` \| `"off"` | — | HTML autocomplete attribute
|
|
72
|
-
| `capitalize` | `boolean` | `false` | Converts all input to uppercase (type `"text"` only)
|
|
73
|
-
| `showMagnifyIcon` | `boolean` | `false` | Shows a magnifying glass icon on the right
|
|
74
|
-
| `strSuggestions` | `string[]` | — | List of suggestions shown in a dropdown as the user types
|
|
75
|
-
| `mobilePicker` | `boolean` | `false` | Shows a country flag/code selector (type `"mobile"` only)
|
|
76
|
-
| `mobileCountryEditable` | `boolean` | `false` | Allows changing the country code (type `"mobile"` + `mobilePicker` only)
|
|
77
|
-
| `mobileWhitelist` | `("BN" \| "MY")[]` | — | Restricts mobile validation to specific countries
|
|
78
|
-
| `mobileView` | `boolean` | `false` | Renders a compact inline layout for mobile screens (label left, input right)
|
|
79
|
-
| `darkMode` | `boolean` | `false` | Applies dark colour scheme to labels
|
|
80
|
-
| `containerClassName` | `tailwind class` | — | Class applied to the outer container
|
|
81
|
-
| `inputClassName` | `tailwind class` | — | Additional class applied to the `<input>` element
|
|
82
|
-
| `onChange` | `(e: any) => void` | `() => {}` | Called on every change; `e.target.value` contains the new value
|
|
83
|
-
| `cellInput` | `CellInput` | — | Refer to Input Utils — enables cell/table editing mode
|
|
58
|
+
| `enterKeyHint` | `string` | — | Label for a phone keyboard's enter key, e.g. `"done"`, `"search"`, `"go"` |
|
|
59
|
+
| `onKeyDown` | `(e) => void` | — | Passed to the `<input>` — e.g. Enter to commit, Escape to cancel |
|
|
60
|
+
| `labelExtra` | `ReactElement` | — | Extra element rendered inline with the label |
|
|
61
|
+
| `infoElement` | `ReactElement` | — | Content shown in an InfoWindow tooltip next to the label |
|
|
62
|
+
| `customElement` | `ReactElement` | — | Custom element rendered to the right of the label row |
|
|
63
|
+
| `pattern` | `string` | — | Regex string applied on submit (overrides type-based validation) |
|
|
64
|
+
| `customErrMsg` | `string` | — | Overrides the default validation error message |
|
|
65
|
+
| `minNumber` | `number` | — | Minimum value (type `"number"` only) |
|
|
66
|
+
| `maxNumber` | `number` | — | Maximum value (type `"number"` only) |
|
|
67
|
+
| `maxLength` | `number` | — | Max character length |
|
|
68
|
+
| `optional` | `boolean` | `false` | Skips validation when `true` |
|
|
69
|
+
| `disabled` | `boolean` | `false` | Disables the input |
|
|
70
|
+
| `autoFocus` | `boolean` | `false` | Focuses the input on mount |
|
|
71
|
+
| `autoComplete` | `"on"` \| `"off"` | — | HTML autocomplete attribute |
|
|
72
|
+
| `capitalize` | `boolean` | `false` | Converts all input to uppercase (type `"text"` only) |
|
|
73
|
+
| `showMagnifyIcon` | `boolean` | `false` | Shows a magnifying glass icon on the right |
|
|
74
|
+
| `strSuggestions` | `string[]` | — | List of suggestions shown in a dropdown as the user types |
|
|
75
|
+
| `mobilePicker` | `boolean` | `false` | Shows a country flag/code selector (type `"mobile"` only) |
|
|
76
|
+
| `mobileCountryEditable` | `boolean` | `false` | Allows changing the country code (type `"mobile"` + `mobilePicker` only) |
|
|
77
|
+
| `mobileWhitelist` | `("BN" \| "MY")[]` | — | Restricts mobile validation to specific countries |
|
|
78
|
+
| `mobileView` | `boolean` | `false` | Renders a compact inline layout for mobile screens (label left, input right) |
|
|
79
|
+
| `darkMode` | `boolean` | `false` | Applies dark colour scheme to labels |
|
|
80
|
+
| `containerClassName` | `tailwind class` | — | Class applied to the outer container |
|
|
81
|
+
| `inputClassName` | `tailwind class` | — | Additional class applied to the `<input>` element |
|
|
82
|
+
| `onChange` | `(e: any) => void` | `() => {}` | Called on every change; `e.target.value` contains the new value |
|
|
83
|
+
| `cellInput` | `CellInput` | — | Refer to Input Utils — enables cell/table editing mode |
|
|
@@ -23,6 +23,8 @@ export const TextInput = () => {
|
|
|
23
23
|
const [suggestText, setSuggestText] = useState("");
|
|
24
24
|
const [regexText, setRegexText] = useState("");
|
|
25
25
|
const [barcodeText, setBarcodeText] = useState("");
|
|
26
|
+
const [serialText, setSerialText] = useState("");
|
|
27
|
+
const [slashSerialText, setSlashSerialText] = useState("");
|
|
26
28
|
|
|
27
29
|
return (
|
|
28
30
|
<>
|
|
@@ -241,6 +243,34 @@ export const TextInput = () => {
|
|
|
241
243
|
/>
|
|
242
244
|
</div>
|
|
243
245
|
</StorySection>
|
|
246
|
+
<StorySection
|
|
247
|
+
title="Barcode Scan (append)"
|
|
248
|
+
description="barcodeMode='append' makes a scan add to the serials already in the box and skips one that is already there. A value uses one separator, picked from the value: the first one in barcodeSeparators that it contains, else the first listed. With [',', '/'] a series starts comma separated (A, B); typing a '/' after the first serial makes later scans slash separated (A/B/C); a value with a comma keeps any '/' as part of a serial. Typing still works."
|
|
249
|
+
>
|
|
250
|
+
<div className="w-full max-w-sm space-y-6">
|
|
251
|
+
<TextInputImpl
|
|
252
|
+
id="batterySerial"
|
|
253
|
+
value={serialText}
|
|
254
|
+
type="text"
|
|
255
|
+
label="Battery Serial Number (commas only, the default)"
|
|
256
|
+
placeholder="Scan each battery label"
|
|
257
|
+
barcodeEnabled
|
|
258
|
+
barcodeMode="append"
|
|
259
|
+
onChange={(e) => setSerialText(e.target.value)}
|
|
260
|
+
/>
|
|
261
|
+
<TextInputImpl
|
|
262
|
+
id="batterySerialSlash"
|
|
263
|
+
value={slashSerialText}
|
|
264
|
+
type="text"
|
|
265
|
+
label="Battery Serial Number (comma, or slash if typed)"
|
|
266
|
+
placeholder="Scan, or type A/ then scan"
|
|
267
|
+
barcodeEnabled
|
|
268
|
+
barcodeMode="append"
|
|
269
|
+
barcodeSeparators={[",", "/"]}
|
|
270
|
+
onChange={(e) => setSlashSerialText(e.target.value)}
|
|
271
|
+
/>
|
|
272
|
+
</div>
|
|
273
|
+
</StorySection>
|
|
244
274
|
<StorySection
|
|
245
275
|
title="Small & Mini sizes"
|
|
246
276
|
description="size='small' reduces padding to px-3 py-2. size='mini' reduces further to p-2."
|
|
@@ -160,13 +160,14 @@ Below `lg` the rail moves into the mobile drawer as a row of icons above the sid
|
|
|
160
160
|
| `renderDashboardFooterContent` | `() => ReactNode` | — | Renders a slot at the bottom of the sidebar, above a border separator |
|
|
161
161
|
| `dashboardFooterClassName` | `string` | — | Tailwind classes applied to the footer slot container |
|
|
162
162
|
| `dashboardContentClassName` | `string` | — | Tailwind classes applied to the main content `<main>` element |
|
|
163
|
+
| `dashboardHeaderHeightClassName` | `string` | `h-16` | Tailwind height classes for the top header bar |
|
|
163
164
|
| `linkType` | `"react" \| "gatsby" \| "next" \| "external" \| "default"` | — | Router adapter passed through to nav links |
|
|
164
165
|
| `custom` | `any` | — | Custom link component used when `linkType` is `"react"`, `"gatsby"`, or `"next"` |
|
|
165
166
|
| `compactMode` | `boolean` | `false` | Tighter rows, smaller icons and a smaller expand chevron, keeping every label |
|
|
166
167
|
| `searchable` | `boolean` | `false` | Shows a filter box. Matches are listed flat, each with the path it sits under (e.g. `Sales › Reports`) |
|
|
167
168
|
| `searchAction` | `ReactElement` | — | A small control inside the right end of the filter box, such as a filter button opening the app's own pop-up. Shown only with `searchable` |
|
|
168
169
|
| `keepSearchAncestors` | `boolean` | `false` | With `searchable`, keeps each match under its parents (a workspace, a folder page), shown open, instead of the flat list. Rows that neither match nor hold a match are left out |
|
|
169
|
-
| `persistKey` | `string` | — | localStorage key that remembers open groups and pages. A new key loads that key's stored state.
|
|
170
|
+
| `persistKey` | `string` | — | localStorage key that remembers open groups and pages. A new key loads that key's stored state. Also keeps how far the sidebar is scrolled for the browser tab (sessionStorage `<persistKey>-scroll`), so a page that mounts its own sidebar opens it at the same place |
|
|
170
171
|
| `defaultExpandedIds` | `string[]` | — | Groups (by `groupId`) and pages (by `id`) open when nothing is stored for them |
|
|
171
172
|
|
|
172
173
|
##### Moving rows in a tree
|
|
@@ -819,3 +819,64 @@ export const LeftNav = () => {
|
|
|
819
819
|
</>
|
|
820
820
|
);
|
|
821
821
|
};
|
|
822
|
+
|
|
823
|
+
// INFO: a long sidebar beside a heavy page, for checking two things: typing in
|
|
824
|
+
// the filter does not redraw the page, and a page that mounts its own sidebar
|
|
825
|
+
// opens it where the last one was scrolled to
|
|
826
|
+
const longNavigation: Navigation[] = Array.from({ length: 80 }, (_, index) => ({
|
|
827
|
+
id: `sheet-${index + 1}`,
|
|
828
|
+
name: `Datasheet ${index + 1}`,
|
|
829
|
+
href: `/sheet-${index + 1}`,
|
|
830
|
+
icon: index % 2 ? FolderIcon : Squares2X2Icon,
|
|
831
|
+
groupId: index < 40 ? "Sales" : "Operations",
|
|
832
|
+
}));
|
|
833
|
+
|
|
834
|
+
const HeavyPage = (props: { title: string }) => {
|
|
835
|
+
const draws = React.useRef(0);
|
|
836
|
+
draws.current += 1;
|
|
837
|
+
return (
|
|
838
|
+
<div className="p-6 text-sm text-gray-600">
|
|
839
|
+
<p className="mb-2 font-semibold text-gray-900">{props.title}</p>
|
|
840
|
+
<p className="mb-4">Page drawn {draws.current} time(s)</p>
|
|
841
|
+
{Array.from({ length: 3000 }, (_, index) => (
|
|
842
|
+
<div key={index} className="border-b border-gray-100 py-1">
|
|
843
|
+
Row {index + 1}
|
|
844
|
+
</div>
|
|
845
|
+
))}
|
|
846
|
+
</div>
|
|
847
|
+
);
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
export const RememberedScroll = () => {
|
|
851
|
+
const [selectedId, setSelectedId] = useState("sheet-1");
|
|
852
|
+
return (
|
|
853
|
+
<StorySection
|
|
854
|
+
title="Remembered scroll and a quiet filter"
|
|
855
|
+
description="Scroll the sidebar down and pick a datasheet near the bottom: each pick mounts a new sidebar, as a page that draws its own does, and it opens where you left it (persistKey keeps the position for the browser tab). Type in the filter: the page's draw count stays the same while you type."
|
|
856
|
+
>
|
|
857
|
+
<div className="w-full h-[32rem] relative overflow-hidden border rounded-lg">
|
|
858
|
+
<LeftNavImpl
|
|
859
|
+
key={selectedId}
|
|
860
|
+
persistKey="story-left-nav-remembered"
|
|
861
|
+
searchable={true}
|
|
862
|
+
keepSearchAncestors={true}
|
|
863
|
+
selectedId={selectedId}
|
|
864
|
+
navigation={longNavigation}
|
|
865
|
+
leftNavMobileMenu={false}
|
|
866
|
+
handleBarsOnClick={(id) => setSelectedId(id)}
|
|
867
|
+
handleToggleLeftNavMobileMenu={() => {}}
|
|
868
|
+
renderDashboardLogo={() => renderLogo()}
|
|
869
|
+
renderDashboardContent={() => (
|
|
870
|
+
<HeavyPage
|
|
871
|
+
title={
|
|
872
|
+
longNavigation.find((each) => each.id === selectedId)?.name ??
|
|
873
|
+
""
|
|
874
|
+
}
|
|
875
|
+
/>
|
|
876
|
+
)}
|
|
877
|
+
renderDashboardHeaderContent={renderHeader}
|
|
878
|
+
/>
|
|
879
|
+
</div>
|
|
880
|
+
</StorySection>
|
|
881
|
+
);
|
|
882
|
+
};
|