powell-react 1.0.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/api/PowellProvider.tsx +37 -0
- package/api/api.ts +126 -0
- package/api/configService.ts +4 -0
- package/api/index.ts +4 -0
- package/api/powellDefaults.ts +11 -0
- package/components/AutoComplete/AutoComplete.scss +126 -0
- package/components/AutoComplete/AutoComplete.tsx +184 -0
- package/components/AutoComplete/index.ts +1 -0
- package/components/Button/Button.tsx +85 -0
- package/components/Button/index.ts +1 -0
- package/components/Checkbox/Checkbox.scss +35 -0
- package/components/Checkbox/Checkbox.tsx +136 -0
- package/components/Checkbox/index.ts +1 -0
- package/components/Dropdown/Dropdown.scss +126 -0
- package/components/Dropdown/Dropdown.tsx +184 -0
- package/components/Dropdown/index.ts +1 -0
- package/components/ErrorMessage/ErrorMessage.scss +7 -0
- package/components/ErrorMessage/ErrorMessage.tsx +23 -0
- package/components/ErrorMessage/index.ts +1 -0
- package/components/FormContainer/FormContainer.tsx +49 -0
- package/components/FormContainer/FormContext.tsx +17 -0
- package/components/FormContainer/index.ts +2 -0
- package/components/InputText/InputText.scss +126 -0
- package/components/InputText/InputText.tsx +184 -0
- package/components/InputText/index.ts +1 -0
- package/components/InputTextarea/InputTextarea.scss +126 -0
- package/components/InputTextarea/InputTextarea.tsx +181 -0
- package/components/InputTextarea/index.ts +1 -0
- package/hooks/index.ts +4 -0
- package/hooks/useApplyConfig.ts +36 -0
- package/hooks/useFormContext.ts +14 -0
- package/hooks/usePowellConfig.ts +64 -0
- package/hooks/useTransform.ts +27 -0
- package/index.js +1 -0
- package/models/common.ts +7 -0
- package/models/config.ts +86 -0
- package/models/forms.ts +23 -0
- package/models/index.ts +3 -0
- package/package.json +16 -0
- package/themes/arya-blue.css +1 -0
- package/themes/arya-green.css +1 -0
- package/themes/arya-orange.css +1 -0
- package/themes/arya-purple.css +1 -0
- package/themes/bootstrap4-dark-blue.css +1 -0
- package/themes/bootstrap4-dark-purple.css +1 -0
- package/themes/bootstrap4-light-blue.css +1 -0
- package/themes/bootstrap4-light-purple.css +1 -0
- package/themes/fluent-light.css +1 -0
- package/themes/lara-dark-amber.css +1 -0
- package/themes/lara-dark-blue.css +1 -0
- package/themes/lara-dark-cyan.css +1 -0
- package/themes/lara-dark-green.css +1 -0
- package/themes/lara-dark-indigo.css +1 -0
- package/themes/lara-dark-pink.css +1 -0
- package/themes/lara-dark-purple.css +1 -0
- package/themes/lara-dark-teal.css +1 -0
- package/themes/lara-light-amber.css +1 -0
- package/themes/lara-light-blue.css +1 -0
- package/themes/lara-light-cyan.css +1 -0
- package/themes/lara-light-green.css +1 -0
- package/themes/lara-light-indigo.css +1 -0
- package/themes/lara-light-pink.css +1 -0
- package/themes/lara-light-purple.css +1 -0
- package/themes/lara-light-teal.css +1 -0
- package/themes/luna-amber.css +1 -0
- package/themes/luna-blue.css +1 -0
- package/themes/luna-green.css +1 -0
- package/themes/luna-pink.css +1 -0
- package/themes/md-dark-deeppurple.css +1 -0
- package/themes/md-dark-indigo.css +1 -0
- package/themes/md-light-deeppurple.css +1 -0
- package/themes/md-light-indigo.css +1 -0
- package/themes/mdc-dark-deeppurple.css +1 -0
- package/themes/mdc-dark-indigo.css +1 -0
- package/themes/mdc-light-deeppurple.css +1 -0
- package/themes/mdc-light-indigo.css +1 -0
- package/themes/mira.css +1 -0
- package/themes/nano.css +1 -0
- package/themes/nova-accent.css +1 -0
- package/themes/nova-alt.css +1 -0
- package/themes/nova.css +1 -0
- package/themes/rhea.css +1 -0
- package/themes/saga-blue.css +1 -0
- package/themes/saga-green.css +1 -0
- package/themes/saga-orange.css +1 -0
- package/themes/saga-purple.css +1 -0
- package/themes/soho-dark.css +1 -0
- package/themes/soho-light.css +1 -0
- package/themes/tailwind-light.css +1 -0
- package/themes/vela-blue.css +1 -0
- package/themes/vela-green.css +1 -0
- package/themes/vela-orange.css +1 -0
- package/themes/vela-purple.css +1 -0
- package/themes/viva-dark.css +1 -0
- package/themes/viva-light.css +1 -0
- package/utils/globalState.ts +96 -0
- package/utils/index.ts +2 -0
- package/utils/utilsService.tsx +39 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
import {PropsWithChildren} from "react";
|
2
|
+
import {configService, powellDefaults, PrimeProvider} from "@powell/api";
|
3
|
+
import {PowellConfig, ThemeName} from "@powell/models";
|
4
|
+
|
5
|
+
const createThemeLink = () => {
|
6
|
+
const headEl = document.head;
|
7
|
+
const linkEl = document.createElement("link");
|
8
|
+
linkEl.rel = "stylesheet";
|
9
|
+
linkEl.type = "text/css";
|
10
|
+
linkEl.id = "powell-theme-link";
|
11
|
+
headEl.appendChild(linkEl);
|
12
|
+
return linkEl;
|
13
|
+
}
|
14
|
+
|
15
|
+
const applyTheme = (theme: ThemeName) => {
|
16
|
+
let themeEl: HTMLLinkElement = document.getElementById('powell-theme-link') as HTMLLinkElement;
|
17
|
+
if (!themeEl) {
|
18
|
+
themeEl = createThemeLink();
|
19
|
+
}
|
20
|
+
const themeLink = `/src/powell/themes/${theme}.css`;
|
21
|
+
themeEl.setAttribute('href', themeLink);
|
22
|
+
}
|
23
|
+
|
24
|
+
export const PowellProvider = (props: PropsWithChildren<{ config?: PowellConfig }>) => {
|
25
|
+
const {children, config} = props;
|
26
|
+
const defaultConfig: PowellConfig = {
|
27
|
+
...powellDefaults,
|
28
|
+
...config
|
29
|
+
};
|
30
|
+
configService.set(defaultConfig);
|
31
|
+
applyTheme(defaultConfig.theme!);
|
32
|
+
return (
|
33
|
+
<PrimeProvider value={defaultConfig}>
|
34
|
+
{children}
|
35
|
+
</PrimeProvider>
|
36
|
+
)
|
37
|
+
}
|
package/api/api.ts
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
import {
|
2
|
+
AutoComplete,
|
3
|
+
AutoCompleteChangeEvent,
|
4
|
+
AutoCompleteCompleteEvent,
|
5
|
+
AutoCompleteDropdownClickEvent,
|
6
|
+
AutoCompleteProps,
|
7
|
+
AutoCompleteSelectEvent,
|
8
|
+
AutoCompleteUnselectEvent,
|
9
|
+
} from "primereact/autocomplete";
|
10
|
+
import {
|
11
|
+
Calendar,
|
12
|
+
CalendarDateTemplateEvent,
|
13
|
+
CalendarMonthChangeEvent,
|
14
|
+
CalendarMonthNavigatorTemplateEvent,
|
15
|
+
CalendarNavigatorTemplateEvent,
|
16
|
+
CalendarProps,
|
17
|
+
CalendarSelectEvent,
|
18
|
+
CalendarViewChangeEvent,
|
19
|
+
CalendarVisibleChangeEvent,
|
20
|
+
CalendarYearNavigatorTemplateEvent,
|
21
|
+
} from "primereact/calendar";
|
22
|
+
import {
|
23
|
+
Checkbox,
|
24
|
+
CheckboxChangeEvent,
|
25
|
+
CheckboxContext,
|
26
|
+
CheckboxPassThroughMethodOptions,
|
27
|
+
CheckboxPassThroughOptions,
|
28
|
+
CheckboxPassThroughType,
|
29
|
+
CheckboxProps,
|
30
|
+
CheckboxState
|
31
|
+
} from "primereact/checkbox";
|
32
|
+
import {Dropdown, DropdownChangeEvent, DropdownFilterEvent, DropdownProps} from "primereact/dropdown";
|
33
|
+
import {FloatLabel} from "primereact/floatlabel";
|
34
|
+
import {InputIcon} from 'primereact/inputicon';
|
35
|
+
import {IconField, IconFieldProps} from "primereact/iconfield";
|
36
|
+
import {InputText, InputTextProps} from "primereact/inputtext";
|
37
|
+
import {InputTextarea, InputTextareaProps} from "primereact/inputtextarea";
|
38
|
+
import {Button, ButtonProps} from "primereact/button";
|
39
|
+
import {Sidebar} from "primereact/sidebar";
|
40
|
+
import {PanelMenu} from 'primereact/panelmenu';
|
41
|
+
import {MenuItem} from "primereact/menuitem";
|
42
|
+
import {
|
43
|
+
addLocale,
|
44
|
+
APIOptions,
|
45
|
+
locale,
|
46
|
+
localeOption,
|
47
|
+
localeOptions,
|
48
|
+
PrimeReactContext,
|
49
|
+
PrimeReactProvider,
|
50
|
+
updateLocaleOption,
|
51
|
+
updateLocaleOptions,
|
52
|
+
ZIndexOptions
|
53
|
+
} from "primereact/api";
|
54
|
+
import {classNames, UniqueComponentId} from "primereact/utils";
|
55
|
+
|
56
|
+
export const PrimeAutoComplete = AutoComplete;
|
57
|
+
export type PrimeAutoCompleteProps = AutoCompleteProps;
|
58
|
+
export type PrimeAutoCompleteSelectEvent = AutoCompleteSelectEvent;
|
59
|
+
export type PrimeAutoCompleteUnselectEvent = AutoCompleteUnselectEvent;
|
60
|
+
export type PrimeAutoCompleteCompleteEvent = AutoCompleteCompleteEvent;
|
61
|
+
export type PrimeAutoCompleteChangeEvent = AutoCompleteChangeEvent;
|
62
|
+
export type PrimeAutoCompleteDropdownClickEvent = AutoCompleteDropdownClickEvent;
|
63
|
+
|
64
|
+
export const PrimeCalendar = Calendar;
|
65
|
+
export type PrimeCalendarProps = CalendarProps;
|
66
|
+
export type PrimeCalendarSelectEvent = CalendarSelectEvent;
|
67
|
+
export type PrimeCalendarNavigatorTemplateEvent = CalendarNavigatorTemplateEvent;
|
68
|
+
export type PrimeCalendarDateTemplateEvent = CalendarDateTemplateEvent;
|
69
|
+
export type PrimeCalendarMonthChangeEvent = CalendarMonthChangeEvent;
|
70
|
+
export type PrimeCalendarVisibleChangeEvent = CalendarVisibleChangeEvent;
|
71
|
+
export type PrimeCalendarViewChangeEvent = CalendarViewChangeEvent;
|
72
|
+
export type PrimeCalendarMonthNavigatorTemplateEvent = CalendarMonthNavigatorTemplateEvent;
|
73
|
+
export type PrimeCalendarYearNavigatorTemplateEvent = CalendarYearNavigatorTemplateEvent;
|
74
|
+
|
75
|
+
export const PrimeCheckbox = Checkbox;
|
76
|
+
export type PrimeCheckboxChangeEvent = CheckboxChangeEvent;
|
77
|
+
export type PrimeCheckboxPassThroughMethodOptions = CheckboxPassThroughMethodOptions;
|
78
|
+
export type PrimeCheckboxPassThroughType<T> = CheckboxPassThroughType<T>;
|
79
|
+
export type PrimeCheckboxPassThroughOptions = CheckboxPassThroughOptions;
|
80
|
+
export type PrimeCheckboxProps = CheckboxProps;
|
81
|
+
export type PrimeCheckboxState = CheckboxState;
|
82
|
+
export type PrimeCheckboxContext = CheckboxContext;
|
83
|
+
|
84
|
+
export const PrimeButton = Button;
|
85
|
+
export type PrimeButtonProps = ButtonProps;
|
86
|
+
|
87
|
+
export const PrimeInputText = InputText;
|
88
|
+
export type PrimeInputTextProps = InputTextProps;
|
89
|
+
|
90
|
+
export const PrimeInputTextarea = InputTextarea;
|
91
|
+
export type PrimeInputTextareaProps = InputTextareaProps;
|
92
|
+
|
93
|
+
export const PrimeIconField = IconField;
|
94
|
+
export type PrimeIconFieldProps = IconFieldProps;
|
95
|
+
|
96
|
+
export const PrimeFloatLabel = FloatLabel;
|
97
|
+
|
98
|
+
export const PrimeInputIcon = InputIcon;
|
99
|
+
|
100
|
+
export type PrimeAPIOptions = APIOptions;
|
101
|
+
|
102
|
+
export const PrimeDropdown = Dropdown;
|
103
|
+
export type PrimeDropdownProps = DropdownProps;
|
104
|
+
export type PrimeDropdownChangeEvent = DropdownChangeEvent;
|
105
|
+
export type PrimeDropdownFilterEvent = DropdownFilterEvent;
|
106
|
+
|
107
|
+
export const PrimeProvider = PrimeReactProvider;
|
108
|
+
|
109
|
+
export const PrimeContext = PrimeReactContext;
|
110
|
+
|
111
|
+
export const PrimePanelMenu = PanelMenu;
|
112
|
+
|
113
|
+
export const PrimeSidebar = Sidebar;
|
114
|
+
|
115
|
+
export type PrimeMenuItem = MenuItem;
|
116
|
+
|
117
|
+
export type PrimeZIndexOptions = ZIndexOptions;
|
118
|
+
|
119
|
+
export const primeLocale = locale;
|
120
|
+
export const primeAddLocale = addLocale;
|
121
|
+
export const primeUpdateLocaleOption = updateLocaleOption;
|
122
|
+
export const primeUpdateLocaleOptions = updateLocaleOptions;
|
123
|
+
export const primeLocaleOption = localeOption;
|
124
|
+
export const primeLocaleOptions = localeOptions;
|
125
|
+
export const PrimeUniqueComponentId = UniqueComponentId;
|
126
|
+
export const primeClassNames = classNames;
|
package/api/index.ts
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
import {PowellConfig} from "@powell/models";
|
2
|
+
|
3
|
+
export const powellDefaults: PowellConfig = {
|
4
|
+
theme: 'lara-light-cyan',
|
5
|
+
rtl: false,
|
6
|
+
showRequiredStar: true,
|
7
|
+
ripple: true,
|
8
|
+
inputSize: 'md',
|
9
|
+
labelPosition: 'fix-top',
|
10
|
+
fixLabelPosition: 'fix-side'
|
11
|
+
}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
.auto-complete-wrapper {
|
2
|
+
.field {
|
3
|
+
display: flex;
|
4
|
+
gap: 0.25rem 1rem;
|
5
|
+
|
6
|
+
> div {
|
7
|
+
flex-grow: 1;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
:where(.p-inputtext, .p-autocomplete) {
|
12
|
+
width: 100%;
|
13
|
+
}
|
14
|
+
|
15
|
+
.p-icon-field {
|
16
|
+
.p-input-icon {
|
17
|
+
z-index: 5;
|
18
|
+
color: var(--text-color-secondary);
|
19
|
+
}
|
20
|
+
|
21
|
+
&.p-icon-field-right {
|
22
|
+
:where(.p-inputtext) {
|
23
|
+
padding-right: 2.5rem;
|
24
|
+
}
|
25
|
+
|
26
|
+
.p-input-icon {
|
27
|
+
right: 0.75rem;
|
28
|
+
left: auto;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
&.p-icon-field-left {
|
33
|
+
:where(.p-inputtext) {
|
34
|
+
padding-left: 2.5rem;
|
35
|
+
}
|
36
|
+
|
37
|
+
.p-input-icon {
|
38
|
+
left: 0.75rem;
|
39
|
+
right: auto;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
&.label-fix-side .field {
|
45
|
+
flex-direction: row;
|
46
|
+
align-items: center;
|
47
|
+
}
|
48
|
+
|
49
|
+
&.label-fix-top .field {
|
50
|
+
flex-direction: column;
|
51
|
+
|
52
|
+
label {
|
53
|
+
margin-bottom: 0.25rem;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
&.addon-before {
|
58
|
+
[class*="icon-"] {
|
59
|
+
:where(.p-inputtext, .p-autocomplete) {
|
60
|
+
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
&.addon-after {
|
66
|
+
&.label-float {
|
67
|
+
.p-inputgroup-addon {
|
68
|
+
border-left: 0;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
[class*="icon-"] {
|
73
|
+
:where(.p-inputtext, .p-autocomplete) {
|
74
|
+
border-radius: var(--border-radius) 0 0 var(--border-radius);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
&[class*="addon-"] {
|
80
|
+
.p-inputgroup {
|
81
|
+
.p-icon-field,
|
82
|
+
.p-float-label {
|
83
|
+
flex-grow: 1;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
&.addon-before :where(.p-inputtext, .p-autocomplete) {
|
88
|
+
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
89
|
+
}
|
90
|
+
|
91
|
+
&.addon-after :where(.p-inputtext, .p-autocomplete) {
|
92
|
+
border-radius: var(--border-radius) 0 0 var(--border-radius);
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
&.is-ltr {
|
97
|
+
direction: ltr;
|
98
|
+
|
99
|
+
&.label-float {
|
100
|
+
&.icon-left .field label {
|
101
|
+
left: 2.5rem;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
&.is-rtl {
|
107
|
+
direction: rtl;
|
108
|
+
|
109
|
+
&.label-float {
|
110
|
+
label {
|
111
|
+
left: auto;
|
112
|
+
right: 0.75rem;
|
113
|
+
}
|
114
|
+
|
115
|
+
&.icon-right .field label {
|
116
|
+
right: 2.5rem;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
&[class*="addon-"] {
|
121
|
+
.p-inputgroup {
|
122
|
+
flex-direction: row-reverse;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
@@ -0,0 +1,184 @@
|
|
1
|
+
import {ChangeEvent, ReactNode, useCallback, useRef, useState} from "react";
|
2
|
+
import {Addon, LabelPosition, Size} from "@powell/models";
|
3
|
+
import {
|
4
|
+
primeClassNames,
|
5
|
+
PrimeFloatLabel,
|
6
|
+
PrimeIconField,
|
7
|
+
PrimeIconFieldProps,
|
8
|
+
PrimeInputIcon,
|
9
|
+
PrimeAutoComplete,
|
10
|
+
PrimeAutoCompleteProps,
|
11
|
+
PrimeUniqueComponentId
|
12
|
+
} from "@powell/api";
|
13
|
+
import {getAddonTemplate, transformer} from "@powell/utils";
|
14
|
+
import {Field, FieldProps} from "formik";
|
15
|
+
import {useApplyConfig, useFormContext} from "@powell/hooks";
|
16
|
+
import {SafeAny} from "@powell/models/common";
|
17
|
+
import {ErrorMessage} from "@powell/components/ErrorMessage";
|
18
|
+
import './AutoComplete.scss';
|
19
|
+
|
20
|
+
interface AutoCompleteProps extends PrimeAutoCompleteProps {
|
21
|
+
name?: string;
|
22
|
+
parseError?: (error: string) => ReactNode;
|
23
|
+
transform?: {
|
24
|
+
input?: (value: SafeAny) => string;
|
25
|
+
output?: (event: ChangeEvent<HTMLInputElement>) => SafeAny;
|
26
|
+
};
|
27
|
+
showRequiredStar?: boolean;
|
28
|
+
rtl?: boolean;
|
29
|
+
label?: string;
|
30
|
+
icon?: string | ReactNode;
|
31
|
+
hint?: string;
|
32
|
+
addon?: Addon;
|
33
|
+
inputSize?: Size;
|
34
|
+
iconPosition?: PrimeIconFieldProps["iconPosition"];
|
35
|
+
labelPosition?: LabelPosition;
|
36
|
+
}
|
37
|
+
|
38
|
+
export const AutoComplete = (props: AutoCompleteProps) => {
|
39
|
+
props = useApplyConfig(props);
|
40
|
+
const {
|
41
|
+
parseError,
|
42
|
+
name,
|
43
|
+
transform = {},
|
44
|
+
iconPosition = 'left',
|
45
|
+
labelPosition,
|
46
|
+
addon,
|
47
|
+
icon,
|
48
|
+
rtl,
|
49
|
+
showRequiredStar,
|
50
|
+
variant,
|
51
|
+
inputSize,
|
52
|
+
...rest
|
53
|
+
} = props;
|
54
|
+
|
55
|
+
const inputId = useRef(PrimeUniqueComponentId());
|
56
|
+
|
57
|
+
// Check if we're in Formik context
|
58
|
+
const formContext = useFormContext();
|
59
|
+
const withinForm = !!formContext && !!name;
|
60
|
+
const isRequired = withinForm && formContext.validationSchema?.fields?.[name].tests?.some((t: SafeAny) => t.OPTIONS.name === 'required');
|
61
|
+
|
62
|
+
// Internal state for non-Formik usage
|
63
|
+
const [internalValue, setInternalValue] = useState(rest.value || '');
|
64
|
+
|
65
|
+
const inputEl = useCallback(() => {
|
66
|
+
const commonProps = {
|
67
|
+
...rest,
|
68
|
+
variant,
|
69
|
+
id: inputId.current,
|
70
|
+
name,
|
71
|
+
};
|
72
|
+
|
73
|
+
if (withinForm) {
|
74
|
+
// if in Formik context
|
75
|
+
return (
|
76
|
+
<Field name={name}>
|
77
|
+
{({field, meta}: FieldProps) => {
|
78
|
+
const {value, onChange} = transformer({
|
79
|
+
value: field.value,
|
80
|
+
onChange: (event: string) => formContext.setFieldValue(name, event),
|
81
|
+
transform: {
|
82
|
+
input: transform.input ?? (value => value),
|
83
|
+
output: transform.output ?? (event => event.target.value)
|
84
|
+
}
|
85
|
+
});
|
86
|
+
|
87
|
+
return (
|
88
|
+
<>
|
89
|
+
<PrimeAutoComplete
|
90
|
+
{...commonProps}
|
91
|
+
value={value}
|
92
|
+
onChange={(event) => {
|
93
|
+
onChange(event);
|
94
|
+
rest.onChange?.(event);
|
95
|
+
}}
|
96
|
+
onBlur={(event) => {
|
97
|
+
field.onBlur(event);
|
98
|
+
rest.onBlur?.(event);
|
99
|
+
}}
|
100
|
+
invalid={!!meta.error}
|
101
|
+
/>
|
102
|
+
<ErrorMessage message={meta.error} parseError={parseError} hint={rest.hint}/>
|
103
|
+
</>
|
104
|
+
);
|
105
|
+
}}
|
106
|
+
</Field>
|
107
|
+
);
|
108
|
+
} else {
|
109
|
+
// if outside Formik context
|
110
|
+
const {value, onChange} = transformer({
|
111
|
+
value: internalValue,
|
112
|
+
onChange: (event: string) => setInternalValue(event),
|
113
|
+
transform: {
|
114
|
+
input: transform.input ?? (value => value),
|
115
|
+
output: transform.output ?? (event => event.target.value)
|
116
|
+
}
|
117
|
+
});
|
118
|
+
|
119
|
+
return (
|
120
|
+
<PrimeAutoComplete
|
121
|
+
{...commonProps}
|
122
|
+
value={value}
|
123
|
+
onChange={(event) => {
|
124
|
+
onChange(event);
|
125
|
+
rest.onChange?.(event);
|
126
|
+
}}
|
127
|
+
onBlur={rest.onBlur}
|
128
|
+
/>
|
129
|
+
);
|
130
|
+
}
|
131
|
+
}, [internalValue]);
|
132
|
+
|
133
|
+
const labelEl = rest.label && (
|
134
|
+
<label htmlFor={inputId.current}>
|
135
|
+
{rest.label}
|
136
|
+
{isRequired && showRequiredStar ? '*' : ''}
|
137
|
+
</label>
|
138
|
+
);
|
139
|
+
|
140
|
+
const iconEl = icon && (
|
141
|
+
typeof icon === 'string'
|
142
|
+
? <PrimeInputIcon className={icon}></PrimeInputIcon>
|
143
|
+
: <PrimeInputIcon>{icon}</PrimeInputIcon>
|
144
|
+
);
|
145
|
+
|
146
|
+
const withIcon = (
|
147
|
+
<PrimeIconField iconPosition={iconPosition}>
|
148
|
+
{iconEl}
|
149
|
+
{inputEl()}
|
150
|
+
</PrimeIconField>
|
151
|
+
);
|
152
|
+
|
153
|
+
return (
|
154
|
+
<div className={primeClassNames('auto-complete-wrapper',
|
155
|
+
`variant-${variant}`,
|
156
|
+
`p-inputtext-${inputSize}`,
|
157
|
+
{
|
158
|
+
[`label-${labelPosition}`]: rest.label,
|
159
|
+
[`icon-${iconPosition}`]: iconEl,
|
160
|
+
'is-rtl': rtl,
|
161
|
+
'is-ltr': !rtl,
|
162
|
+
'addon-before': addon?.before,
|
163
|
+
'addon-after': addon?.after,
|
164
|
+
})}>
|
165
|
+
<div className="field">
|
166
|
+
{labelPosition !== 'float' && labelEl}
|
167
|
+
<div className={primeClassNames({"p-inputgroup": addon})}>
|
168
|
+
{getAddonTemplate(addon?.before)}
|
169
|
+
{
|
170
|
+
labelPosition === 'float' ? (
|
171
|
+
<PrimeFloatLabel>
|
172
|
+
{icon ? withIcon : inputEl()}
|
173
|
+
{labelEl}
|
174
|
+
</PrimeFloatLabel>
|
175
|
+
) : (
|
176
|
+
icon ? withIcon : inputEl()
|
177
|
+
)
|
178
|
+
}
|
179
|
+
{getAddonTemplate(addon?.after)}
|
180
|
+
</div>
|
181
|
+
</div>
|
182
|
+
</div>
|
183
|
+
);
|
184
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from "./AutoComplete";
|
@@ -0,0 +1,85 @@
|
|
1
|
+
import {memo, MouseEvent, useRef, useState} from "react";
|
2
|
+
import {PrimeButton, PrimeButtonProps, primeClassNames} from "@powell/api";
|
3
|
+
import {ButtonAppearance} from "@powell/models";
|
4
|
+
|
5
|
+
type ButtonState = 'default' | 'loading' | 'next';
|
6
|
+
|
7
|
+
interface ButtonProps extends Omit<PrimeButtonProps, "loading" | "link" | "text" | "outlined"> {
|
8
|
+
async?: true;
|
9
|
+
onClickAsync?: (event: { loadingCallback: (ok?: boolean) => void, event: MouseEvent<HTMLButtonElement> }) => void;
|
10
|
+
appearance?: ButtonAppearance;
|
11
|
+
nextLabel?: string;
|
12
|
+
nextIcon?: string;
|
13
|
+
nextRaised?: boolean;
|
14
|
+
nextAppearance?: ButtonAppearance;
|
15
|
+
nextSeverity?: ButtonProps['severity'];
|
16
|
+
state?: ButtonState;
|
17
|
+
onStateChange?: (state: ButtonState) => void;
|
18
|
+
}
|
19
|
+
|
20
|
+
type ButtonTempProps = Pick<ButtonProps, "label" | "icon" | "raised" | "appearance" | "severity">;
|
21
|
+
|
22
|
+
export const Button = memo((props: ButtonProps) => {
|
23
|
+
const {
|
24
|
+
async,
|
25
|
+
onClickAsync,
|
26
|
+
onClick,
|
27
|
+
nextLabel,
|
28
|
+
nextIcon,
|
29
|
+
nextRaised,
|
30
|
+
nextSeverity,
|
31
|
+
nextAppearance,
|
32
|
+
state = 'default',
|
33
|
+
onStateChange,
|
34
|
+
type = 'button',
|
35
|
+
...rest
|
36
|
+
} = props;
|
37
|
+
|
38
|
+
const [_state, _setState] = useState<ButtonState>(state);
|
39
|
+
|
40
|
+
const getButtonTempProps = (newState: ButtonState) => {
|
41
|
+
return {
|
42
|
+
label: newState === 'default' ? props.label : (nextLabel ?? props.label),
|
43
|
+
icon: newState === 'default' ? props.icon : (nextIcon ?? props.icon),
|
44
|
+
appearance: newState === 'default' ? props.appearance : (nextAppearance ?? props.appearance),
|
45
|
+
raised: newState === 'default' ? props.raised : (nextRaised ?? props.raised),
|
46
|
+
severity: newState === 'default' ? props.severity : (nextSeverity ?? props.severity),
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
const tempProps = useRef<ButtonTempProps>(getButtonTempProps(state));
|
51
|
+
|
52
|
+
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
|
53
|
+
if (async) {
|
54
|
+
onClickAsync?.({event, loadingCallback: removeLoading});
|
55
|
+
_setState('loading');
|
56
|
+
onStateChange?.('loading');
|
57
|
+
} else {
|
58
|
+
onClick?.(event);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
const removeLoading = (toggleState?: boolean) => {
|
63
|
+
const newState = toggleState ? 'next' : 'default';
|
64
|
+
tempProps.current = getButtonTempProps(newState);
|
65
|
+
_setState(newState);
|
66
|
+
onStateChange?.(newState);
|
67
|
+
}
|
68
|
+
|
69
|
+
return (
|
70
|
+
<PrimeButton
|
71
|
+
type={type}
|
72
|
+
{...rest}
|
73
|
+
onClick={handleClick}
|
74
|
+
label={async ? tempProps.current.label : props.label}
|
75
|
+
icon={async ? tempProps.current.icon : props.icon}
|
76
|
+
severity={async ? tempProps.current.severity : props.severity}
|
77
|
+
raised={async ? tempProps.current.raised : props.raised}
|
78
|
+
text={async ? tempProps.current.appearance === 'text' : props.appearance === 'text'}
|
79
|
+
outlined={async ? tempProps.current.appearance === 'outlined' : props.appearance === 'outlined'}
|
80
|
+
link={async ? tempProps.current.appearance === 'link' : props.appearance === 'link'}
|
81
|
+
loading={_state === 'loading'}
|
82
|
+
className={primeClassNames(props.className, `state-${_state}`)}
|
83
|
+
/>
|
84
|
+
)
|
85
|
+
})
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from "./Button";
|
@@ -0,0 +1,35 @@
|
|
1
|
+
.checkbox-wrapper {
|
2
|
+
.field {
|
3
|
+
display: flex;
|
4
|
+
gap: 0.25rem 1rem;
|
5
|
+
|
6
|
+
> .field-inner {
|
7
|
+
flex-grow: 1;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
:where(.p-checkbox) {
|
12
|
+
width: 100%;
|
13
|
+
}
|
14
|
+
|
15
|
+
&.label-fix-side .field {
|
16
|
+
flex-direction: row;
|
17
|
+
align-items: center;
|
18
|
+
}
|
19
|
+
|
20
|
+
&.label-fix-top .field {
|
21
|
+
flex-direction: column;
|
22
|
+
|
23
|
+
label {
|
24
|
+
margin-bottom: 0.25rem;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
&.is-ltr {
|
29
|
+
direction: ltr;
|
30
|
+
}
|
31
|
+
|
32
|
+
&.is-rtl {
|
33
|
+
direction: rtl;
|
34
|
+
}
|
35
|
+
}
|