@douglasneuroinformatics/libui 2.0.9 → 2.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.
- package/dist/components/Form/NumberField/NumberField.d.ts.map +1 -1
- package/dist/components/Form/NumberField/NumberField.js +2 -0
- package/dist/components/Form/NumberField/NumberFieldRadio.d.ts +1 -1
- package/dist/components/Form/NumberField/NumberFieldRadio.d.ts.map +1 -1
- package/dist/components/Form/NumberField/NumberFieldSelect.d.ts +9 -0
- package/dist/components/Form/NumberField/NumberFieldSelect.d.ts.map +1 -0
- package/dist/components/Form/NumberField/NumberFieldSelect.js +16 -0
- package/dist/hooks/useDownload.d.ts +11 -4
- package/dist/hooks/useDownload.d.ts.map +1 -1
- package/dist/hooks/useDownload.js +2 -2
- package/package.json +2 -2
- package/src/components/Form/NumberField/NumberField.tsx +2 -0
- package/src/components/Form/NumberField/NumberFieldRadio.tsx +1 -1
- package/src/components/Form/NumberField/NumberFieldSelect.tsx +46 -0
- package/src/hooks/useDownload.ts +19 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberField.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/NumberField/NumberField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"NumberField.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/NumberField/NumberField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAErF,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAExF,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,GAAG,qBAAqB,GAAG,sBAAsB,CAAC;AAEtG,eAAO,MAAM,WAAW,UAAW,gBAAgB,sBAOlD,CAAC"}
|
|
@@ -2,11 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import { match } from 'ts-pattern';
|
|
3
3
|
import { NumberFieldInput } from './NumberFieldInput.js';
|
|
4
4
|
import { NumberFieldRadio } from './NumberFieldRadio.js';
|
|
5
|
+
import { NumberFieldSelect } from './NumberFieldSelect.js';
|
|
5
6
|
import { NumberFieldSlider } from './NumberFieldSlider.js';
|
|
6
7
|
export const NumberField = (props) => {
|
|
7
8
|
return match(props)
|
|
8
9
|
.with({ variant: 'input' }, (props) => React.createElement(NumberFieldInput, { ...props }))
|
|
9
10
|
.with({ variant: 'slider' }, (props) => React.createElement(NumberFieldSlider, { ...props }))
|
|
10
11
|
.with({ variant: 'radio' }, (props) => React.createElement(NumberFieldRadio, { ...props }))
|
|
12
|
+
.with({ variant: 'select' }, (props) => React.createElement(NumberFieldSelect, { ...props }))
|
|
11
13
|
.exhaustive();
|
|
12
14
|
};
|
|
@@ -3,7 +3,7 @@ import type { NumberFormField } from '@douglasneuroinformatics/libui-form-types'
|
|
|
3
3
|
import type { Simplify } from 'type-fest';
|
|
4
4
|
import type { BaseFieldComponentProps } from '../types.js';
|
|
5
5
|
export type NumberFieldRadioProps = Simplify<BaseFieldComponentProps<number> & Extract<NumberFormField, {
|
|
6
|
-
|
|
6
|
+
options: object;
|
|
7
7
|
}>>;
|
|
8
8
|
export declare const NumberFieldRadio: ({ description, error, label, name, options, setValue, value }: NumberFieldRadioProps) => React.JSX.Element;
|
|
9
9
|
//# sourceMappingURL=NumberFieldRadio.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberFieldRadio.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/NumberField/NumberFieldRadio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAO1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAC1C,uBAAuB,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,eAAe,EAAE;IAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"NumberFieldRadio.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/NumberField/NumberFieldRadio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAO1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAC1C,uBAAuB,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,eAAe,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAChF,CAAC;AAEF,eAAO,MAAM,gBAAgB,kEAQ1B,qBAAqB,sBAiCvB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { NumberFormField } from '@douglasneuroinformatics/libui-form-types';
|
|
3
|
+
import type { Simplify } from 'type-fest';
|
|
4
|
+
import { type BaseFieldComponentProps } from '../types.js';
|
|
5
|
+
export type NumberFieldSelectProps<T extends number = number> = Simplify<BaseFieldComponentProps<T> & Extract<NumberFormField<T>, {
|
|
6
|
+
options: object;
|
|
7
|
+
}>>;
|
|
8
|
+
export declare const NumberFieldSelect: <T extends number = number>({ description, error, label, name, options, setValue, value }: NumberFieldSelectProps<T>) => React.JSX.Element;
|
|
9
|
+
//# sourceMappingURL=NumberFieldSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NumberFieldSelect.d.ts","sourceRoot":"","sources":["../../../../src/components/Form/NumberField/NumberFieldSelect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAK1C,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,QAAQ,CACtE,uBAAuB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAC9E,CAAC;AAEF,eAAO,MAAM,iBAAiB,6FAQ3B,uBAAuB,CAAC,CAAC,sBAuB3B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Label } from '../../Label/Label.js';
|
|
3
|
+
import { Select } from '../../Select/Select.js';
|
|
4
|
+
import { FieldGroup } from '../FieldGroup/FieldGroup.js';
|
|
5
|
+
import {} from '../types.js';
|
|
6
|
+
export const NumberFieldSelect = ({ description, error, label, name, options, setValue, value }) => {
|
|
7
|
+
return (React.createElement(FieldGroup, null,
|
|
8
|
+
React.createElement(FieldGroup.Row, null,
|
|
9
|
+
React.createElement(Label, null, label),
|
|
10
|
+
React.createElement(FieldGroup.Description, { description: description })),
|
|
11
|
+
React.createElement(Select, { name: name, value: value?.toString() ?? '', onValueChange: (value) => setValue(parseFloat(value)) },
|
|
12
|
+
React.createElement(Select.Trigger, { "data-cy": `${name}-select-trigger`, "data-testid": `${name}-select-trigger` },
|
|
13
|
+
React.createElement(Select.Value, null)),
|
|
14
|
+
React.createElement(Select.Content, { "data-cy": `${name}-select-content`, "data-testid": `${name}-select-content` }, Object.keys(options).map((option) => (React.createElement(Select.Item, { key: option, value: option }, options[option]))))),
|
|
15
|
+
React.createElement(FieldGroup.Error, { error: error })));
|
|
16
|
+
};
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import type { Promisable } from 'type-fest';
|
|
2
|
-
type
|
|
3
|
-
blobType: 'image/png';
|
|
4
|
-
} : {
|
|
2
|
+
type DownloadTextOptions = {
|
|
5
3
|
blobType: 'text/csv' | 'text/plain';
|
|
6
4
|
};
|
|
5
|
+
type DownloadBlobOptions = {
|
|
6
|
+
blobType: 'application/zip' | 'image/jpeg' | 'image/png' | 'image/webp';
|
|
7
|
+
};
|
|
8
|
+
interface DownloadFunction {
|
|
9
|
+
(filename: string, data: Blob, options: DownloadBlobOptions): Promise<void>;
|
|
10
|
+
(filename: string, data: () => Promisable<Blob>, options: DownloadBlobOptions): Promise<void>;
|
|
11
|
+
(filename: string, data: string, options?: DownloadTextOptions): Promise<void>;
|
|
12
|
+
(filename: string, data: () => Promisable<string>, options?: DownloadTextOptions): Promise<void>;
|
|
13
|
+
}
|
|
7
14
|
/**
|
|
8
15
|
* Used to trigger downloads of arbitrary data to the client
|
|
9
16
|
* @returns A function to invoke the download
|
|
10
17
|
*/
|
|
11
|
-
export declare function useDownload():
|
|
18
|
+
export declare function useDownload(): DownloadFunction;
|
|
12
19
|
export {};
|
|
13
20
|
//# sourceMappingURL=useDownload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDownload.d.ts","sourceRoot":"","sources":["../../src/hooks/useDownload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAI5C,KAAK,
|
|
1
|
+
{"version":3,"file":"useDownload.d.ts","sourceRoot":"","sources":["../../src/hooks/useDownload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAI5C,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,UAAU,GAAG,YAAY,CAAC;CACrC,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,iBAAiB,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,CAAC;CACzE,CAAC;AAGF,UAAU,gBAAgB;IACxB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClG;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,gBAAgB,CA0C9C"}
|
|
@@ -22,9 +22,9 @@ export function useDownload() {
|
|
|
22
22
|
setState(null);
|
|
23
23
|
}
|
|
24
24
|
}, [state]);
|
|
25
|
-
return async (filename,
|
|
25
|
+
return async (filename, _data, options) => {
|
|
26
26
|
try {
|
|
27
|
-
const data = await
|
|
27
|
+
const data = typeof _data === 'function' ? await _data() : _data;
|
|
28
28
|
if (typeof data !== 'string' && !options?.blobType) {
|
|
29
29
|
throw new Error("argument 'blobType' must be defined when download is called with a Blob object");
|
|
30
30
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@douglasneuroinformatics/libui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0
|
|
4
|
+
"version": "2.2.0",
|
|
5
5
|
"packageManager": "pnpm@8.15.3",
|
|
6
6
|
"description": "Generic UI components for DNP projects, built using React and TailwindCSS",
|
|
7
7
|
"author": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@douglasneuroinformatics/libjs": "^0.3.1",
|
|
59
|
-
"@douglasneuroinformatics/libui-form-types": "^0.
|
|
59
|
+
"@douglasneuroinformatics/libui-form-types": "^0.7.0",
|
|
60
60
|
"@headlessui/react": "^1.7.18",
|
|
61
61
|
"@headlessui/tailwindcss": "^0.2.0",
|
|
62
62
|
"@heroicons/react": "^2.1.3",
|
|
@@ -4,6 +4,7 @@ import { match } from 'ts-pattern';
|
|
|
4
4
|
|
|
5
5
|
import { NumberFieldInput, type NumberFieldInputProps } from './NumberFieldInput.js';
|
|
6
6
|
import { NumberFieldRadio, type NumberFieldRadioProps } from './NumberFieldRadio.js';
|
|
7
|
+
import { NumberFieldSelect } from './NumberFieldSelect.js';
|
|
7
8
|
import { NumberFieldSlider, type NumberFieldSliderProps } from './NumberFieldSlider.js';
|
|
8
9
|
|
|
9
10
|
export type NumberFieldProps = NumberFieldInputProps | NumberFieldRadioProps | NumberFieldSliderProps;
|
|
@@ -13,5 +14,6 @@ export const NumberField = (props: NumberFieldProps) => {
|
|
|
13
14
|
.with({ variant: 'input' }, (props) => <NumberFieldInput {...props} />)
|
|
14
15
|
.with({ variant: 'slider' }, (props) => <NumberFieldSlider {...props} />)
|
|
15
16
|
.with({ variant: 'radio' }, (props) => <NumberFieldRadio {...props} />)
|
|
17
|
+
.with({ variant: 'select' }, (props) => <NumberFieldSelect {...props} />)
|
|
16
18
|
.exhaustive();
|
|
17
19
|
};
|
|
@@ -11,7 +11,7 @@ import { FieldGroup } from '../FieldGroup/FieldGroup.js';
|
|
|
11
11
|
import type { BaseFieldComponentProps } from '../types.js';
|
|
12
12
|
|
|
13
13
|
export type NumberFieldRadioProps = Simplify<
|
|
14
|
-
BaseFieldComponentProps<number> & Extract<NumberFormField, {
|
|
14
|
+
BaseFieldComponentProps<number> & Extract<NumberFormField, { options: object }>
|
|
15
15
|
>;
|
|
16
16
|
|
|
17
17
|
export const NumberFieldRadio = ({
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { NumberFormField } from '@douglasneuroinformatics/libui-form-types';
|
|
4
|
+
import type { Simplify } from 'type-fest';
|
|
5
|
+
|
|
6
|
+
import { Label } from '../../Label/Label.js';
|
|
7
|
+
import { Select } from '../../Select/Select.js';
|
|
8
|
+
import { FieldGroup } from '../FieldGroup/FieldGroup.js';
|
|
9
|
+
import { type BaseFieldComponentProps } from '../types.js';
|
|
10
|
+
|
|
11
|
+
export type NumberFieldSelectProps<T extends number = number> = Simplify<
|
|
12
|
+
BaseFieldComponentProps<T> & Extract<NumberFormField<T>, { options: object }>
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
export const NumberFieldSelect = <T extends number = number>({
|
|
16
|
+
description,
|
|
17
|
+
error,
|
|
18
|
+
label,
|
|
19
|
+
name,
|
|
20
|
+
options,
|
|
21
|
+
setValue,
|
|
22
|
+
value
|
|
23
|
+
}: NumberFieldSelectProps<T>) => {
|
|
24
|
+
return (
|
|
25
|
+
<FieldGroup>
|
|
26
|
+
<FieldGroup.Row>
|
|
27
|
+
<Label>{label}</Label>
|
|
28
|
+
<FieldGroup.Description description={description} />
|
|
29
|
+
</FieldGroup.Row>
|
|
30
|
+
<Select name={name} value={value?.toString() ?? ''} onValueChange={(value) => setValue(parseFloat(value) as T)}>
|
|
31
|
+
<Select.Trigger data-cy={`${name}-select-trigger`} data-testid={`${name}-select-trigger`}>
|
|
32
|
+
<Select.Value />
|
|
33
|
+
</Select.Trigger>
|
|
34
|
+
<Select.Content data-cy={`${name}-select-content`} data-testid={`${name}-select-content`}>
|
|
35
|
+
{Object.keys(options).map((option) => (
|
|
36
|
+
<Select.Item key={option} value={option}>
|
|
37
|
+
{/** option needs to be type number, but no sense converting it when it is coerced right back anyways */}
|
|
38
|
+
{options[option as any as T]}
|
|
39
|
+
</Select.Item>
|
|
40
|
+
))}
|
|
41
|
+
</Select.Content>
|
|
42
|
+
</Select>
|
|
43
|
+
<FieldGroup.Error error={error} />
|
|
44
|
+
</FieldGroup>
|
|
45
|
+
);
|
|
46
|
+
};
|
package/src/hooks/useDownload.ts
CHANGED
|
@@ -4,18 +4,30 @@ import type { Promisable } from 'type-fest';
|
|
|
4
4
|
|
|
5
5
|
import { useNotificationsStore } from './useNotificationsStore.js';
|
|
6
6
|
|
|
7
|
-
type
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
type DownloadTextOptions = {
|
|
8
|
+
blobType: 'text/csv' | 'text/plain';
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type DownloadBlobOptions = {
|
|
12
|
+
blobType: 'application/zip' | 'image/jpeg' | 'image/png' | 'image/webp';
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
16
|
+
interface DownloadFunction {
|
|
17
|
+
(filename: string, data: Blob, options: DownloadBlobOptions): Promise<void>;
|
|
18
|
+
(filename: string, data: () => Promisable<Blob>, options: DownloadBlobOptions): Promise<void>;
|
|
19
|
+
(filename: string, data: string, options?: DownloadTextOptions): Promise<void>;
|
|
20
|
+
(filename: string, data: () => Promisable<string>, options?: DownloadTextOptions): Promise<void>;
|
|
21
|
+
}
|
|
10
22
|
|
|
11
23
|
/**
|
|
12
24
|
* Used to trigger downloads of arbitrary data to the client
|
|
13
25
|
* @returns A function to invoke the download
|
|
14
26
|
*/
|
|
15
|
-
export function useDownload() {
|
|
27
|
+
export function useDownload(): DownloadFunction {
|
|
16
28
|
const notifications = useNotificationsStore();
|
|
17
29
|
const [state, setState] = useState<{
|
|
18
|
-
blobType:
|
|
30
|
+
blobType: string;
|
|
19
31
|
data: Blob | string;
|
|
20
32
|
filename: string;
|
|
21
33
|
} | null>(null);
|
|
@@ -38,13 +50,9 @@ export function useDownload() {
|
|
|
38
50
|
}
|
|
39
51
|
}, [state]);
|
|
40
52
|
|
|
41
|
-
return async
|
|
42
|
-
filename: string,
|
|
43
|
-
fetchData: () => Promisable<T>,
|
|
44
|
-
options?: DownloadOptions<T>
|
|
45
|
-
) => {
|
|
53
|
+
return async (filename, _data, options) => {
|
|
46
54
|
try {
|
|
47
|
-
const data = await
|
|
55
|
+
const data = typeof _data === 'function' ? await _data() : _data;
|
|
48
56
|
if (typeof data !== 'string' && !options?.blobType) {
|
|
49
57
|
throw new Error("argument 'blobType' must be defined when download is called with a Blob object");
|
|
50
58
|
}
|