@giro-ds/react 12.1.1 → 12.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/index.cjs CHANGED
@@ -2928,6 +2928,7 @@ const ICON_KEY_MAP = {
2928
2928
  capslock: reactIcons.KeyboardShiftUppercase20Regular,
2929
2929
  downkeyboard: reactIcons.ChevronDown20Regular,
2930
2930
  emoji: reactIcons.Emoji20Regular,
2931
+ enterNumpad: reactIcons.ArrowImport20Regular,
2931
2932
  };
2932
2933
  const SHARED_DISPLAY = {
2933
2934
  '{capslock}': iconSlot('capslock'),
@@ -2953,9 +2954,11 @@ const LAYOUT_DISPLAY = {
2953
2954
  const EMOTICON_KEY = '{emoticon}';
2954
2955
  const DOWN_KEYBOARD_KEY = '{downkeyboard}';
2955
2956
  const ENTER_KEY = '{enter}';
2956
- const removeKeyFromLayout = (layout, key) => Object.fromEntries(Object.entries(layout).map(([layoutName, rows]) => [
2957
+ const removeKeyFromLayout = (layout, key, skipLayouts = []) => Object.fromEntries(Object.entries(layout).map(([layoutName, rows]) => [
2957
2958
  layoutName,
2958
- rows.map((row) => row.split(key).join(' ').replace(/\s+/g, ' ').trim()),
2959
+ skipLayouts.includes(layoutName)
2960
+ ? rows
2961
+ : rows.map((row) => row.split(key).join(' ').replace(/\s+/g, ' ').trim()),
2959
2962
  ]));
2960
2963
  const replaceKeyWithBlank = (layout, key) => Object.fromEntries(Object.entries(layout).map(([layoutName, rows]) => [
2961
2964
  layoutName,
@@ -2968,7 +2971,8 @@ const QWERTY_LOWERCASE = [
2968
2971
  '{shift} z x c v b n m {bksp}',
2969
2972
  '{numbers} {alt} {space} . {enter}',
2970
2973
  ];
2971
- const NUMPAD = ['1 2 3', '4 5 6', '7 8 9', '{bksp} 0 {abc}'];
2974
+ const NUMPAD = ['1 2 3', '4 5 6', '7 8 9', '{abc} 0 {bksp}'];
2975
+ const NUMPAD_WITH_ENTER = ['1 2 3 -', '4 5 6 _', '7 8 9 {bksp}', '{abc} 0 . {enter}'];
2972
2976
  const SHARED_LAYOUTS = {
2973
2977
  shift: [
2974
2978
  '1 2 3 4 5 6 7 8 9 0',
@@ -3018,11 +3022,17 @@ const NATIVE_LAYOUTS = {
3018
3022
  const NATIVE_LAYOUT_KEYS = new Set([
3019
3023
  'default', 'numeric',
3020
3024
  ]);
3021
- const getNativeLayout = (type, Emoji = true, showDownKeyboardButton = true, isFixed = false, showEnterKey = true, showTypeSwitchKey = true) => {
3025
+ const getNativeLayout = (type, Emoji = true, showDownKeyboardButton = true, isFixed = false, showEnterKey = true, showTypeSwitchKey = true, numpadWithEnter = false) => {
3022
3026
  const layout = NATIVE_LAYOUTS[type] ?? NATIVE_LAYOUTS.default ?? null;
3023
3027
  if (!layout)
3024
3028
  return null;
3025
- let computedLayout = layout;
3029
+ let computedLayout = numpadWithEnter
3030
+ ? {
3031
+ ...layout,
3032
+ ...(type === 'numeric' ? { default: NUMPAD_WITH_ENTER } : {}),
3033
+ numbers: NUMPAD_WITH_ENTER,
3034
+ }
3035
+ : layout;
3026
3036
  if (!Emoji) {
3027
3037
  computedLayout = removeKeyFromLayout(computedLayout, EMOTICON_KEY);
3028
3038
  }
@@ -3030,7 +3040,9 @@ const getNativeLayout = (type, Emoji = true, showDownKeyboardButton = true, isFi
3030
3040
  computedLayout = removeKeyFromLayout(computedLayout, DOWN_KEYBOARD_KEY);
3031
3041
  }
3032
3042
  if (!showEnterKey) {
3033
- computedLayout = removeKeyFromLayout(computedLayout, ENTER_KEY);
3043
+ // Numpad layouts always preserve {enter}; only remove from QWERTY layouts
3044
+ const numpadLayouts = type === 'numeric' ? ['default', 'numbers'] : ['numbers'];
3045
+ computedLayout = removeKeyFromLayout(computedLayout, ENTER_KEY, numpadLayouts);
3034
3046
  }
3035
3047
  if (!showTypeSwitchKey) {
3036
3048
  computedLayout = removeKeyFromLayout(computedLayout, '{numbers}');
@@ -3101,13 +3113,16 @@ const ACCENT_OPTIONS = {
3101
3113
  * <VirtualKeyboard targetRef={inputRef} value={value} onChange={setValue} />
3102
3114
  * ```
3103
3115
  */
3104
- const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onChange, onKeyPress, onTypeChange, maxLength, Emoji = false, className, id, placeholder = 'Digite aqui...', helperText, error, errorMessage, targetRef, textFieldScale = 1, showEnterKey = true, showTypeSwitchKey = true, }) => {
3116
+ const VirtualKeyboard = ({ variant = 'native', type = 'default', value, onChange, onKeyPress, onEnterPress, onTypeChange, maxLength, Emoji = false, className, id, placeholder = 'Digite aqui...', helperText, error, errorMessage, targetRef, textFieldScale = 1, showEnterKey = true, showTypeSwitchKey = true, numpadWithEnter = false, }) => {
3117
+ const [internalValue, setInternalValue] = React.useState(value ?? '');
3105
3118
  const [layoutName, setLayoutName] = React.useState('default');
3106
3119
  const [capsLockOn, setCapsLockOn] = React.useState(false);
3107
3120
  const [accentMenu, setAccentMenu] = React.useState(null);
3108
3121
  const [accentMenuOffsetX, setAccentMenuOffsetX] = React.useState(0);
3109
- const [activeLayout, setActiveLayout] = React.useState(getNativeLayout(type, Emoji, variant === 'native', variant === 'fixed', showEnterKey, showTypeSwitchKey));
3122
+ const [activeLayout, setActiveLayout] = React.useState(getNativeLayout(type, Emoji, variant === 'native', variant === 'fixed', showEnterKey, showTypeSwitchKey, numpadWithEnter));
3110
3123
  const visualType = NATIVE_LAYOUT_KEYS.has(type) ? type : 'default';
3124
+ const effectiveValue = onChange !== undefined ? (value ?? '') : internalValue;
3125
+ const isNumpadLayout = (type === 'numeric' && layoutName === 'default') || layoutName === 'numbers';
3111
3126
  const [isOpen, setIsOpen] = React.useState(variant !== 'native');
3112
3127
  const hideTimeoutRef = React.useRef(null);
3113
3128
  const scrollTimeoutRef = React.useRef(null);
@@ -3120,15 +3135,15 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3120
3135
  const keyboardInstanceRef = React.useRef(null);
3121
3136
  const accentMenuRef = React.useRef(null);
3122
3137
  const accentButtonRef = React.useRef(null);
3123
- const valueRef = React.useRef(value);
3138
+ const valueRef = React.useRef(value ?? '');
3124
3139
  const [iconSlots, setIconSlots] = React.useState([]);
3125
3140
  const [keyPreview, setKeyPreview] = React.useState(null);
3126
3141
  const [keyPreviewOffsetX, setKeyPreviewOffsetX] = React.useState(0);
3127
3142
  const keyPreviewRef = React.useRef(null);
3128
3143
  const [containerWidth, setContainerWidth] = React.useState(Infinity);
3129
3144
  React.useEffect(() => {
3130
- valueRef.current = value;
3131
- }, [value]);
3145
+ valueRef.current = effectiveValue;
3146
+ }, [effectiveValue]);
3132
3147
  const clearLongPressTimeout = React.useCallback(() => {
3133
3148
  if (longPressTimeoutRef.current !== null) {
3134
3149
  clearTimeout(longPressTimeoutRef.current);
@@ -3143,8 +3158,8 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3143
3158
  keyboardInstanceRef.current?.setInput(nextValue);
3144
3159
  }, []);
3145
3160
  React.useEffect(() => {
3146
- syncKeyboardInput(value);
3147
- }, [value, syncKeyboardInput]);
3161
+ syncKeyboardInput(effectiveValue);
3162
+ }, [effectiveValue, syncKeyboardInput]);
3148
3163
  React.useEffect(() => {
3149
3164
  onTypeChange?.(type);
3150
3165
  }, [type, onTypeChange]);
@@ -3222,8 +3237,8 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3222
3237
  React.useEffect(() => {
3223
3238
  setLayoutName('default');
3224
3239
  setCapsLockOn(false);
3225
- setActiveLayout(getNativeLayout(type, Emoji, variant === 'native', variant === 'fixed', showEnterKey, showTypeSwitchKey));
3226
- }, [type, Emoji, variant, showEnterKey, showTypeSwitchKey]);
3240
+ setActiveLayout(getNativeLayout(type, Emoji, variant === 'native', variant === 'fixed', showEnterKey, showTypeSwitchKey, numpadWithEnter));
3241
+ }, [type, Emoji, variant, showEnterKey, showTypeSwitchKey, numpadWithEnter]);
3227
3242
  React.useEffect(() => {
3228
3243
  if (!Emoji && layoutName === 'emoticon') {
3229
3244
  setLayoutName(type === 'numeric' ? 'abc' : 'default');
@@ -3303,7 +3318,10 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3303
3318
  if (newSlots.length === 0)
3304
3319
  return;
3305
3320
  newSlots.forEach((s) => s.setAttribute('data-icon-root', 'true'));
3306
- setIconSlots((prev) => [...prev, ...newSlots]);
3321
+ setIconSlots((prev) => [
3322
+ ...prev.filter((slot) => container.contains(slot)),
3323
+ ...newSlots,
3324
+ ]);
3307
3325
  };
3308
3326
  registerNewSlots();
3309
3327
  const observer = new MutationObserver(() => {
@@ -3314,7 +3332,7 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3314
3332
  return () => {
3315
3333
  observer.disconnect();
3316
3334
  };
3317
- }, []);
3335
+ }, [variant]);
3318
3336
  React.useEffect(() => {
3319
3337
  closeAccentMenu();
3320
3338
  setAccentMenuOffsetX(0);
@@ -3396,6 +3414,8 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3396
3414
  const currentValue = valueRef.current;
3397
3415
  if (maxLength === undefined || currentValue.length < maxLength) {
3398
3416
  const nextValue = `${currentValue}${heldKey}`;
3417
+ if (onChange === undefined)
3418
+ setInternalValue(nextValue);
3399
3419
  onChange?.(nextValue);
3400
3420
  onKeyPress?.(heldKey);
3401
3421
  syncKeyboardInput(nextValue);
@@ -3429,6 +3449,8 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3429
3449
  return;
3430
3450
  }
3431
3451
  const nextValue = `${currentValue}${accentedChar}`;
3452
+ if (onChange === undefined)
3453
+ setInternalValue(nextValue);
3432
3454
  onChange?.(nextValue);
3433
3455
  onKeyPress?.(accentedChar);
3434
3456
  closeAccentMenu();
@@ -3519,12 +3541,16 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3519
3541
  if (isHeldAccentKey) {
3520
3542
  return;
3521
3543
  }
3544
+ if (button === '{enter}') {
3545
+ onEnterPress?.();
3546
+ }
3522
3547
  onKeyPress?.(button);
3523
3548
  }, [
3524
3549
  type,
3525
3550
  layoutName,
3526
3551
  capsLockOn,
3527
3552
  onKeyPress,
3553
+ onEnterPress,
3528
3554
  onTypeChange,
3529
3555
  Emoji,
3530
3556
  variant,
@@ -3551,8 +3577,10 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3551
3577
  }
3552
3578
  if (maxLength !== undefined && input.length > maxLength)
3553
3579
  return;
3580
+ if (onChange === undefined)
3581
+ setInternalValue(input);
3554
3582
  onChange?.(input);
3555
- }, [maxLength, onChange, syncKeyboardInput]);
3583
+ }, [maxLength, onChange, setInternalValue, syncKeyboardInput]);
3556
3584
  const portalSizes = React.useMemo(() => {
3557
3585
  if (containerWidth <= 360)
3558
3586
  return { preview: 42, option: 44, fontSize: 'var(--font-size-16)' };
@@ -3568,15 +3596,16 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3568
3596
  const baseDisplay = LAYOUT_DISPLAY[visualType];
3569
3597
  if (!baseDisplay)
3570
3598
  return baseDisplay;
3571
- if (variant !== 'fixed') {
3572
- return baseDisplay;
3599
+ const display = { ...baseDisplay };
3600
+ if (numpadWithEnter && isNumpadLayout) {
3601
+ display['{enter}'] = '<span data-icon-key="enterNumpad"></span>';
3573
3602
  }
3574
- return {
3575
- ...baseDisplay,
3576
- '{bksp}': (baseDisplay['{bksp}'] ?? '').replace(/\s*Apagar$/, ''),
3577
- };
3578
- }, [visualType, variant]);
3579
- const keyboardEl = activeLayout ? (jsxRuntime.jsxs("div", { ref: keyboardWrapperRef, className: clsx(styles$k.keyboardWrapper, ((type === 'numeric' && layoutName === 'default') || layoutName === 'numbers' || type === 'default') && styles$k.keyboardNumpadActive), onPointerDownCapture: handleLongPressStart, onPointerUpCapture: handleLongPressEnd, onPointerLeave: handleLongPressEnd, onPointerCancelCapture: handleLongPressEnd, children: [jsxRuntime.jsx(Keyboard, { keyboardRef: (instance) => {
3603
+ if (variant === 'fixed') {
3604
+ display['{bksp}'] = (display['{bksp}'] ?? '').replace(/\s*Apagar$/, '');
3605
+ }
3606
+ return display;
3607
+ }, [visualType, variant, numpadWithEnter, isNumpadLayout]);
3608
+ const keyboardEl = activeLayout ? (jsxRuntime.jsxs("div", { ref: keyboardWrapperRef, className: clsx(styles$k.keyboardWrapper, isNumpadLayout && styles$k.keyboardNumpadActive), onPointerDownCapture: handleLongPressStart, onPointerUpCapture: handleLongPressEnd, onPointerLeave: handleLongPressEnd, onPointerCancelCapture: handleLongPressEnd, children: [jsxRuntime.jsx(Keyboard, { keyboardRef: (instance) => {
3580
3609
  keyboardInstanceRef.current = instance;
3581
3610
  if (instance) {
3582
3611
  instance.setInput(valueRef.current);
@@ -3614,9 +3643,9 @@ const VirtualKeyboard = ({ variant = 'native', type = 'default', value = '', onC
3614
3643
  event.stopPropagation();
3615
3644
  }, onClick: () => handleAccentSelect(option), children: option }, `${accentMenu.sourceKey}-${option}`))) }, rowIndex))) }), document.body))] })) : null;
3616
3645
  if (variant === 'native' && typeof document !== 'undefined') {
3617
- return reactDom.createPortal(jsxRuntime.jsx("div", { id: id, className: clsx(styles$k.overlay, { [styles$k.overlayOpen]: isOpen }, styles$k[`layout--${visualType}`], className), children: keyboardEl }), document.body);
3646
+ return reactDom.createPortal(jsxRuntime.jsx("div", { id: id, className: clsx(styles$k.overlay, { [styles$k.overlayOpen]: isOpen }, styles$k[isNumpadLayout ? 'layout--numeric' : 'layout--default'], className), children: keyboardEl }), document.body);
3618
3647
  }
3619
- return (jsxRuntime.jsxs("div", { id: id, className: clsx(styles$k.container, styles$k[`mode--${variant}`], styles$k[`layout--${visualType}`], className), children: [variant === 'fixed' && (jsxRuntime.jsx("div", { className: styles$k.textFieldContainer, children: jsxRuntime.jsx(TextField, { placeholder: placeholder, value: value, onChange: onChange, helperText: helperText, error: error, errorMessage: errorMessage, readOnly: true, disableAutoComplete: true, maxLength: maxLength, attachedToVirtualKeyboard: true, className: styles$k.textFieldWrapper, scale: textFieldScale }) })), keyboardEl] }));
3648
+ return (jsxRuntime.jsxs("div", { id: id, className: clsx(styles$k.container, styles$k[`mode--${variant}`], styles$k[isNumpadLayout ? 'layout--numeric' : 'layout--default'], className), children: [variant === 'fixed' && (jsxRuntime.jsx("div", { className: styles$k.textFieldContainer, children: jsxRuntime.jsx(TextField, { placeholder: placeholder, value: effectiveValue, onChange: onChange, helperText: helperText, error: error, errorMessage: errorMessage, readOnly: true, disableAutoComplete: true, maxLength: maxLength, attachedToVirtualKeyboard: true, className: styles$k.textFieldWrapper, scale: textFieldScale }) })), keyboardEl] }));
3620
3649
  };
3621
3650
 
3622
3651
  var styles$j = {"container":"TextField-module__container___WJHFR","inputWrapper":"TextField-module__inputWrapper___INjfd","inputContainer":"TextField-module__inputContainer___3EsFJ","icon":"TextField-module__icon___p1vwi","clearButton":"TextField-module__clearButton___kgOot","inputWithIcon":"TextField-module__inputWithIcon___shqkL","helperText":"TextField-module__helperText___d5QGC","error":"TextField-module__error___IGQzp","disabled":"TextField-module__disabled___roIKP","attachedToVirtualKeyboard":"TextField-module__attachedToVirtualKeyboard___fuO2O","errorWithMessage":"TextField-module__errorWithMessage___m-5AA","clearButtonIcon":"TextField-module__clearButtonIcon___Z2iyc"};