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.
Files changed (98) hide show
  1. package/api/PowellProvider.tsx +37 -0
  2. package/api/api.ts +126 -0
  3. package/api/configService.ts +4 -0
  4. package/api/index.ts +4 -0
  5. package/api/powellDefaults.ts +11 -0
  6. package/components/AutoComplete/AutoComplete.scss +126 -0
  7. package/components/AutoComplete/AutoComplete.tsx +184 -0
  8. package/components/AutoComplete/index.ts +1 -0
  9. package/components/Button/Button.tsx +85 -0
  10. package/components/Button/index.ts +1 -0
  11. package/components/Checkbox/Checkbox.scss +35 -0
  12. package/components/Checkbox/Checkbox.tsx +136 -0
  13. package/components/Checkbox/index.ts +1 -0
  14. package/components/Dropdown/Dropdown.scss +126 -0
  15. package/components/Dropdown/Dropdown.tsx +184 -0
  16. package/components/Dropdown/index.ts +1 -0
  17. package/components/ErrorMessage/ErrorMessage.scss +7 -0
  18. package/components/ErrorMessage/ErrorMessage.tsx +23 -0
  19. package/components/ErrorMessage/index.ts +1 -0
  20. package/components/FormContainer/FormContainer.tsx +49 -0
  21. package/components/FormContainer/FormContext.tsx +17 -0
  22. package/components/FormContainer/index.ts +2 -0
  23. package/components/InputText/InputText.scss +126 -0
  24. package/components/InputText/InputText.tsx +184 -0
  25. package/components/InputText/index.ts +1 -0
  26. package/components/InputTextarea/InputTextarea.scss +126 -0
  27. package/components/InputTextarea/InputTextarea.tsx +181 -0
  28. package/components/InputTextarea/index.ts +1 -0
  29. package/hooks/index.ts +4 -0
  30. package/hooks/useApplyConfig.ts +36 -0
  31. package/hooks/useFormContext.ts +14 -0
  32. package/hooks/usePowellConfig.ts +64 -0
  33. package/hooks/useTransform.ts +27 -0
  34. package/index.js +1 -0
  35. package/models/common.ts +7 -0
  36. package/models/config.ts +86 -0
  37. package/models/forms.ts +23 -0
  38. package/models/index.ts +3 -0
  39. package/package.json +16 -0
  40. package/themes/arya-blue.css +1 -0
  41. package/themes/arya-green.css +1 -0
  42. package/themes/arya-orange.css +1 -0
  43. package/themes/arya-purple.css +1 -0
  44. package/themes/bootstrap4-dark-blue.css +1 -0
  45. package/themes/bootstrap4-dark-purple.css +1 -0
  46. package/themes/bootstrap4-light-blue.css +1 -0
  47. package/themes/bootstrap4-light-purple.css +1 -0
  48. package/themes/fluent-light.css +1 -0
  49. package/themes/lara-dark-amber.css +1 -0
  50. package/themes/lara-dark-blue.css +1 -0
  51. package/themes/lara-dark-cyan.css +1 -0
  52. package/themes/lara-dark-green.css +1 -0
  53. package/themes/lara-dark-indigo.css +1 -0
  54. package/themes/lara-dark-pink.css +1 -0
  55. package/themes/lara-dark-purple.css +1 -0
  56. package/themes/lara-dark-teal.css +1 -0
  57. package/themes/lara-light-amber.css +1 -0
  58. package/themes/lara-light-blue.css +1 -0
  59. package/themes/lara-light-cyan.css +1 -0
  60. package/themes/lara-light-green.css +1 -0
  61. package/themes/lara-light-indigo.css +1 -0
  62. package/themes/lara-light-pink.css +1 -0
  63. package/themes/lara-light-purple.css +1 -0
  64. package/themes/lara-light-teal.css +1 -0
  65. package/themes/luna-amber.css +1 -0
  66. package/themes/luna-blue.css +1 -0
  67. package/themes/luna-green.css +1 -0
  68. package/themes/luna-pink.css +1 -0
  69. package/themes/md-dark-deeppurple.css +1 -0
  70. package/themes/md-dark-indigo.css +1 -0
  71. package/themes/md-light-deeppurple.css +1 -0
  72. package/themes/md-light-indigo.css +1 -0
  73. package/themes/mdc-dark-deeppurple.css +1 -0
  74. package/themes/mdc-dark-indigo.css +1 -0
  75. package/themes/mdc-light-deeppurple.css +1 -0
  76. package/themes/mdc-light-indigo.css +1 -0
  77. package/themes/mira.css +1 -0
  78. package/themes/nano.css +1 -0
  79. package/themes/nova-accent.css +1 -0
  80. package/themes/nova-alt.css +1 -0
  81. package/themes/nova.css +1 -0
  82. package/themes/rhea.css +1 -0
  83. package/themes/saga-blue.css +1 -0
  84. package/themes/saga-green.css +1 -0
  85. package/themes/saga-orange.css +1 -0
  86. package/themes/saga-purple.css +1 -0
  87. package/themes/soho-dark.css +1 -0
  88. package/themes/soho-light.css +1 -0
  89. package/themes/tailwind-light.css +1 -0
  90. package/themes/vela-blue.css +1 -0
  91. package/themes/vela-green.css +1 -0
  92. package/themes/vela-orange.css +1 -0
  93. package/themes/vela-purple.css +1 -0
  94. package/themes/viva-dark.css +1 -0
  95. package/themes/viva-light.css +1 -0
  96. package/utils/globalState.ts +96 -0
  97. package/utils/index.ts +2 -0
  98. 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;
@@ -0,0 +1,4 @@
1
+ import {globalState} from "@powell/utils";
2
+ import {PowellConfig} from "@powell/models";
3
+
4
+ export const configService = globalState<PowellConfig>({});
package/api/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './api';
2
+ export * from './configService';
3
+ export * from './powellDefaults';
4
+ export * from './PowellProvider';
@@ -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
+ }