@ews-admin/global-design-system 1.6.0 → 1.8.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/index.js CHANGED
@@ -3,13 +3,13 @@
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
 
6
- function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
6
+ function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);else for(t in e)e[t]&&(n&&(n+=" "),n+=t);return n}function clsx(){for(var e,t,f=0,n="";f<arguments.length;)(e=arguments[f++])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
7
7
 
8
8
  const LOCAL_PORTS = {
9
9
  bff: 8082,
10
10
  loginBff: 8080,
11
11
  app: 3000,
12
- login: 3001,
12
+ login: 4001,
13
13
  dashboard: 3002,
14
14
  admin: 3008,
15
15
  };
@@ -64,7 +64,7 @@ function createEnvConfig(env, overrides) {
64
64
  * Available country codes supported by the platform
65
65
  */
66
66
  const COUNTRY_CODES = [
67
- { code: "+221", country: "SN" }, // Senegal
67
+ { code: "+221", country: "SN" },
68
68
  { code: "+235", country: "TD" }, // Chad
69
69
  ];
70
70
  /**
@@ -32608,11 +32608,11 @@ const Input = React.forwardRef(({ className, variant = "default", size = "md", l
32608
32608
  if (label) {
32609
32609
  // Render checkbox with built-in label
32610
32610
  return (jsxRuntime.jsx("div", { className: cn("space-y-1", fullWidth ? "w-full" : "w-auto"), children: jsxRuntime.jsxs("div", { className: "flex items-start space-x-3", children: [jsxRuntime.jsx("input", { id: inputId, type: actualType, className: cn("mt-0.5", // Slight top margin to align with first line of text
32611
- className), ref: ref, ...props }), jsxRuntime.jsxs("div", { className: "flex-1", children: [jsxRuntime.jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium cursor-pointer text-ews-gray-700", children: [label, required && jsxRuntime.jsx("span", { className: "ml-1 text-ews-error", children: "*" })] }), (error || helperText) && (jsxRuntime.jsx("p", { className: cn("mt-1 text-sm", error ? "text-ews-error" : "text-ews-gray-500"), children: error || helperText }))] })] }) }));
32611
+ className), ref: ref, onChange: onChange, onBlur: onBlur, ...props }), jsxRuntime.jsxs("div", { className: "flex-1", children: [jsxRuntime.jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium cursor-pointer text-ews-gray-700", children: [label, required && jsxRuntime.jsx("span", { className: "ml-1 text-ews-error", children: "*" })] }), (error || helperText) && (jsxRuntime.jsx("p", { className: cn("mt-1 text-sm", error ? "text-ews-error" : "text-ews-gray-500"), children: error || helperText }))] })] }) }));
32612
32612
  }
32613
32613
  else {
32614
32614
  // Render just the checkbox for external label usage
32615
- return (jsxRuntime.jsx("input", { id: inputId, type: actualType, className: cn(className), ref: ref, ...props }));
32615
+ return (jsxRuntime.jsx("input", { id: inputId, type: actualType, className: cn(className), ref: ref, onChange: onChange, onBlur: onBlur, ...props }));
32616
32616
  }
32617
32617
  }
32618
32618
  // Default rendering for non-checkbox inputs
@@ -32939,23 +32939,29 @@ var isWeb = typeof window !== 'undefined' &&
32939
32939
  typeof document !== 'undefined';
32940
32940
 
32941
32941
  function cloneObject(data) {
32942
+ let copy;
32943
+ const isArray = Array.isArray(data);
32944
+ const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false;
32942
32945
  if (data instanceof Date) {
32943
- return new Date(data);
32946
+ copy = new Date(data);
32944
32947
  }
32945
- const isFileListInstance = typeof FileList !== 'undefined' && data instanceof FileList;
32946
- if (isWeb && (data instanceof Blob || isFileListInstance)) {
32947
- return data;
32948
+ else if (!(isWeb && (data instanceof Blob || isFileListInstance)) &&
32949
+ (isArray || isObject(data))) {
32950
+ copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
32951
+ if (!isArray && !isPlainObject(data)) {
32952
+ copy = data;
32953
+ }
32954
+ else {
32955
+ for (const key in data) {
32956
+ if (data.hasOwnProperty(key)) {
32957
+ copy[key] = cloneObject(data[key]);
32958
+ }
32959
+ }
32960
+ }
32948
32961
  }
32949
- const isArray = Array.isArray(data);
32950
- if (!isArray && !(isObject(data) && isPlainObject(data))) {
32962
+ else {
32951
32963
  return data;
32952
32964
  }
32953
- const copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
32954
- for (const key in data) {
32955
- if (Object.prototype.hasOwnProperty.call(data, key)) {
32956
- copy[key] = cloneObject(data[key]);
32957
- }
32958
- }
32959
32965
  return copy;
32960
32966
  }
32961
32967
 
@@ -32981,8 +32987,6 @@ var get = (object, path, defaultValue) => {
32981
32987
 
32982
32988
  var isBoolean = (value) => typeof value === 'boolean';
32983
32989
 
32984
- var isFunction = (value) => typeof value === 'function';
32985
-
32986
32990
  var set = (object, path, value) => {
32987
32991
  let index = -1;
32988
32992
  const tempPath = isKey(path) ? [path] : stringToPath(path);
@@ -33010,21 +33014,50 @@ var set = (object, path, value) => {
33010
33014
 
33011
33015
  const EVENTS = {
33012
33016
  BLUR: 'blur',
33013
- CHANGE: 'change'};
33017
+ FOCUS_OUT: 'focusout',
33018
+ CHANGE: 'change',
33019
+ };
33014
33020
  const VALIDATION_MODE = {
33021
+ onBlur: 'onBlur',
33022
+ onChange: 'onChange',
33023
+ onSubmit: 'onSubmit',
33024
+ onTouched: 'onTouched',
33015
33025
  all: 'all',
33016
33026
  };
33017
33027
 
33028
+ const HookFormContext = React.createContext(null);
33029
+ HookFormContext.displayName = 'HookFormContext';
33018
33030
  /**
33019
- * Separate context for `control` to prevent unnecessary rerenders.
33020
- * Internal hooks that only need control use this instead of full form context.
33021
- */
33022
- const HookFormControlContext = React.createContext(null);
33023
- HookFormControlContext.displayName = 'HookFormControlContext';
33024
- /**
33025
- * @internal Internal hook to access only control from context.
33031
+ * This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
33032
+ *
33033
+ * @remarks
33034
+ * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
33035
+ *
33036
+ * @returns return all useForm methods
33037
+ *
33038
+ * @example
33039
+ * ```tsx
33040
+ * function App() {
33041
+ * const methods = useForm();
33042
+ * const onSubmit = data => console.log(data);
33043
+ *
33044
+ * return (
33045
+ * <FormProvider {...methods} >
33046
+ * <form onSubmit={methods.handleSubmit(onSubmit)}>
33047
+ * <NestedInput />
33048
+ * <input type="submit" />
33049
+ * </form>
33050
+ * </FormProvider>
33051
+ * );
33052
+ * }
33053
+ *
33054
+ * function NestedInput() {
33055
+ * const { register } = useFormContext(); // retrieve all hook methods
33056
+ * return <input {...register("test")} />;
33057
+ * }
33058
+ * ```
33026
33059
  */
33027
- const useFormControlContext = () => React.useContext(HookFormControlContext);
33060
+ const useFormContext = () => React.useContext(HookFormContext);
33028
33061
 
33029
33062
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
33030
33063
  const result = {
@@ -33078,8 +33111,8 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
33078
33111
  * ```
33079
33112
  */
33080
33113
  function useFormState(props) {
33081
- const formControl = useFormControlContext();
33082
- const { control = formControl, disabled, name, exact } = props || {};
33114
+ const methods = useFormContext();
33115
+ const { control = methods.control, disabled, name, exact } = props || {};
33083
33116
  const [formState, updateFormState] = React.useState(control._formState);
33084
33117
  const _localProxyFormState = React.useRef({
33085
33118
  isDirty: false,
@@ -33113,11 +33146,14 @@ var isString = (value) => typeof value === 'string';
33113
33146
 
33114
33147
  var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => {
33115
33148
  if (isString(names)) {
33149
+ isGlobal && _names.watch.add(names);
33116
33150
  return get(formValues, names, defaultValue);
33117
33151
  }
33118
33152
  if (Array.isArray(names)) {
33119
- return names.map((fieldName) => (get(formValues, fieldName)));
33153
+ return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName),
33154
+ get(formValues, fieldName)));
33120
33155
  }
33156
+ isGlobal && (_names.watchAll = true);
33121
33157
  return formValues;
33122
33158
  };
33123
33159
 
@@ -33125,10 +33161,10 @@ var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
33125
33161
 
33126
33162
  function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
33127
33163
  if (isPrimitive(object1) || isPrimitive(object2)) {
33128
- return Object.is(object1, object2);
33164
+ return object1 === object2;
33129
33165
  }
33130
33166
  if (isDateObject(object1) && isDateObject(object2)) {
33131
- return Object.is(object1.getTime(), object2.getTime());
33167
+ return object1.getTime() === object2.getTime();
33132
33168
  }
33133
33169
  const keys1 = Object.keys(object1);
33134
33170
  const keys2 = Object.keys(object2);
@@ -33151,7 +33187,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
33151
33187
  (isObject(val1) && isObject(val2)) ||
33152
33188
  (Array.isArray(val1) && Array.isArray(val2))
33153
33189
  ? !deepEqual(val1, val2, _internal_visited)
33154
- : !Object.is(val1, val2)) {
33190
+ : val1 !== val2) {
33155
33191
  return false;
33156
33192
  }
33157
33193
  }
@@ -33176,73 +33212,38 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
33176
33212
  * ```
33177
33213
  */
33178
33214
  function useWatch(props) {
33179
- const formControl = useFormControlContext();
33180
- const { control = formControl, name, defaultValue, disabled, exact, compute, } = props || {};
33215
+ const methods = useFormContext();
33216
+ const { control = methods.control, name, defaultValue, disabled, exact, compute, } = props || {};
33181
33217
  const _defaultValue = React.useRef(defaultValue);
33182
33218
  const _compute = React.useRef(compute);
33183
33219
  const _computeFormValues = React.useRef(undefined);
33184
- const _prevControl = React.useRef(control);
33185
- const _prevName = React.useRef(name);
33186
33220
  _compute.current = compute;
33187
- const [value, updateValue] = React.useState(() => {
33188
- const defaultValue = control._getWatch(name, _defaultValue.current);
33189
- return _compute.current ? _compute.current(defaultValue) : defaultValue;
33190
- });
33191
- const getCurrentOutput = React.useCallback((values) => {
33192
- const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
33193
- return _compute.current ? _compute.current(formValues) : formValues;
33194
- }, [control._formValues, control._names, name]);
33195
- const refreshValue = React.useCallback((values) => {
33196
- if (!disabled) {
33197
- const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
33198
- if (_compute.current) {
33199
- const computedFormValues = _compute.current(formValues);
33200
- if (!deepEqual(computedFormValues, _computeFormValues.current)) {
33201
- updateValue(computedFormValues);
33202
- _computeFormValues.current = computedFormValues;
33221
+ const defaultValueMemo = React.useMemo(() => control._getWatch(name, _defaultValue.current), [control, name]);
33222
+ const [value, updateValue] = React.useState(_compute.current ? _compute.current(defaultValueMemo) : defaultValueMemo);
33223
+ useIsomorphicLayoutEffect(() => control._subscribe({
33224
+ name,
33225
+ formState: {
33226
+ values: true,
33227
+ },
33228
+ exact,
33229
+ callback: (formState) => {
33230
+ if (!disabled) {
33231
+ const formValues = generateWatchOutput(name, control._names, formState.values || control._formValues, false, _defaultValue.current);
33232
+ if (_compute.current) {
33233
+ const computedFormValues = _compute.current(formValues);
33234
+ if (!deepEqual(computedFormValues, _computeFormValues.current)) {
33235
+ updateValue(computedFormValues);
33236
+ _computeFormValues.current = computedFormValues;
33237
+ }
33238
+ }
33239
+ else {
33240
+ updateValue(formValues);
33203
33241
  }
33204
33242
  }
33205
- else {
33206
- updateValue(formValues);
33207
- }
33208
- }
33209
- }, [control._formValues, control._names, disabled, name]);
33210
- useIsomorphicLayoutEffect(() => {
33211
- if (_prevControl.current !== control ||
33212
- !deepEqual(_prevName.current, name)) {
33213
- _prevControl.current = control;
33214
- _prevName.current = name;
33215
- refreshValue();
33216
- }
33217
- return control._subscribe({
33218
- name,
33219
- formState: {
33220
- values: true,
33221
- },
33222
- exact,
33223
- callback: (formState) => {
33224
- refreshValue(formState.values);
33225
- },
33226
- });
33227
- }, [control, exact, name, refreshValue]);
33243
+ },
33244
+ }), [control, disabled, name, exact]);
33228
33245
  React.useEffect(() => control._removeUnmounted());
33229
- // If name or control changed for this render, synchronously reflect the
33230
- // latest value so callers (like useController) see the correct value
33231
- // immediately on the same render.
33232
- // Optimize: Check control reference first before expensive deepEqual
33233
- const controlChanged = _prevControl.current !== control;
33234
- const prevName = _prevName.current;
33235
- // Cache the computed output to avoid duplicate calls within the same render
33236
- // We include shouldReturnImmediate in deps to ensure proper recomputation
33237
- const computedOutput = React.useMemo(() => {
33238
- if (disabled) {
33239
- return null;
33240
- }
33241
- const nameChanged = !controlChanged && !deepEqual(prevName, name);
33242
- const shouldReturnImmediate = controlChanged || nameChanged;
33243
- return shouldReturnImmediate ? getCurrentOutput() : null;
33244
- }, [disabled, controlChanged, name, prevName, getCurrentOutput]);
33245
- return computedOutput !== null ? computedOutput : value;
33246
+ return value;
33246
33247
  }
33247
33248
 
33248
33249
  /**
@@ -33270,20 +33271,20 @@ function useWatch(props) {
33270
33271
  * ```
33271
33272
  */
33272
33273
  function useController(props) {
33273
- const formControl = useFormControlContext();
33274
- const { name, disabled, control = formControl, shouldUnregister, defaultValue, exact = true, } = props;
33274
+ const methods = useFormContext();
33275
+ const { name, disabled, control = methods.control, shouldUnregister, defaultValue, } = props;
33275
33276
  const isArrayField = isNameInFieldArray(control._names.array, name);
33276
33277
  const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
33277
33278
  const value = useWatch({
33278
33279
  control,
33279
33280
  name,
33280
33281
  defaultValue: defaultValueMemo,
33281
- exact,
33282
+ exact: true,
33282
33283
  });
33283
33284
  const formState = useFormState({
33284
33285
  control,
33285
33286
  name,
33286
- exact,
33287
+ exact: true,
33287
33288
  });
33288
33289
  const _props = React.useRef(props);
33289
33290
  const _previousNameRef = React.useRef(undefined);
@@ -33331,12 +33332,12 @@ function useController(props) {
33331
33332
  }), [name, control._formValues]);
33332
33333
  const ref = React.useCallback((elm) => {
33333
33334
  const field = get(control._fields, name);
33334
- if (field && field._f && elm) {
33335
+ if (field && elm) {
33335
33336
  field._f.ref = {
33336
- focus: () => isFunction(elm.focus) && elm.focus(),
33337
- select: () => isFunction(elm.select) && elm.select(),
33338
- setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
33339
- reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
33337
+ focus: () => elm.focus && elm.focus(),
33338
+ select: () => elm.select && elm.select(),
33339
+ setCustomValidity: (message) => elm.setCustomValidity(message),
33340
+ reportValidity: () => elm.reportValidity(),
33340
33341
  };
33341
33342
  }
33342
33343
  }, [control._fields, name]);
@@ -33370,7 +33371,7 @@ function useController(props) {
33370
33371
  };
33371
33372
  updateMounted(name, true);
33372
33373
  if (_shouldUnregisterField) {
33373
- const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue));
33374
+ const value = cloneObject(get(control._options.defaultValues, name));
33374
33375
  set(control._defaultValues, name, value);
33375
33376
  if (isUndefined(get(control._formValues, name))) {
33376
33377
  set(control._formValues, name, value);
@@ -33443,9 +33444,6 @@ function useController(props) {
33443
33444
  */
33444
33445
  const Controller = (props) => props.render(useController(props));
33445
33446
 
33446
- const HookFormContext = React.createContext(null);
33447
- HookFormContext.displayName = 'HookFormContext';
33448
-
33449
33447
  function useSelectField({ name, control, options: _options, rules, defaultValue, }) {
33450
33448
  const { field, fieldState: { error, invalid }, } = useController({
33451
33449
  name,
@@ -33969,7 +33967,14 @@ const PhoneInput = React.forwardRef(({ countryCode, onCountryCodeChange, onChang
33969
33967
  // when the user changes the dropdown without retyping the number.
33970
33968
  const el = nativeRef.current;
33971
33969
  if (el && onChange) {
33972
- const numeric = formatNumeric(el.value);
33970
+ let numeric = formatNumeric(el.value);
33971
+ // Strip new country code digits if already present at the start
33972
+ // (e.g. local part "221778384499" when switching to +221).
33973
+ const newCodeDigits = formatNumeric(newCode);
33974
+ if (newCodeDigits && numeric.startsWith(newCodeDigits)) {
33975
+ numeric = numeric.slice(newCodeDigits.length);
33976
+ el.value = numeric;
33977
+ }
33973
33978
  const fullValue = numeric ? `${newCode}${numeric}` : "";
33974
33979
  // Pass the value string directly — RHF's Controller field.onChange
33975
33980
  // accepts raw values, avoiding unreliable fake-event parsing.
@@ -33987,7 +33992,14 @@ const PhoneInput = React.forwardRef(({ countryCode, onCountryCodeChange, onChang
33987
33992
  }, [value]);
33988
33993
  const handleChange = (e) => {
33989
33994
  // Enforce digits-only in the displayed field.
33990
- const numeric = formatNumeric(e.target.value);
33995
+ let numeric = formatNumeric(e.target.value);
33996
+ // Strip country code digits if user typed or pasted the full number
33997
+ // (e.g. typed "+221778384499" → formatNumeric gives "221778384499"
33998
+ // which would produce "+221221778384499" without this guard).
33999
+ const codeDigits = formatNumeric(activeCode);
34000
+ if (codeDigits && numeric.startsWith(codeDigits)) {
34001
+ numeric = numeric.slice(codeDigits.length);
34002
+ }
33991
34003
  if (e.target.value !== numeric) {
33992
34004
  e.target.value = numeric;
33993
34005
  }
@@ -34095,8 +34107,8 @@ const PROMED_THEME = {
34095
34107
  const MED_THEME = {
34096
34108
  name: "MED",
34097
34109
  colors: {
34098
- primary: "#3BA1A1", // Teal for patients (calming, trustworthy)
34099
- secondary: "#6B73FF", // Soft purple-blue (suggested secondary for MED)
34110
+ primary: "#3BA1A1",
34111
+ secondary: "#6B73FF",
34100
34112
  primaryHover: "#308181",
34101
34113
  secondaryHover: "#5a61e6",
34102
34114
  primaryLight: "#a8d5d5",