@workday/canvas-kit-react 11.0.0-alpha.671-next.0 → 11.0.0-alpha.693-next.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 (152) hide show
  1. package/checkbox/lib/CheckBackground.tsx +48 -0
  2. package/checkbox/lib/Checkbox.tsx +18 -355
  3. package/checkbox/lib/CheckboxCheck.tsx +81 -0
  4. package/checkbox/lib/CheckboxContainer.tsx +58 -0
  5. package/checkbox/lib/CheckboxInput.tsx +279 -0
  6. package/checkbox/lib/CheckboxRipple.tsx +21 -0
  7. package/collection/lib/useCursorListModel.tsx +86 -90
  8. package/collection/lib/useListItemAllowChildStrings.ts +3 -3
  9. package/collection/lib/useListRenderItem.tsx +1 -1
  10. package/combobox/lib/hooks/useComboboxInput.ts +1 -0
  11. package/combobox/lib/hooks/useComboboxKeyboardTypeAhead.ts +3 -3
  12. package/combobox/lib/hooks/useComboboxModel.tsx +1 -2
  13. package/common/README.md +32 -14
  14. package/common/lib/styles/errorRing.ts +2 -2
  15. package/common/lib/styles/focusRing.ts +4 -17
  16. package/dist/commonjs/avatar/lib/Avatar.js +1 -1
  17. package/dist/commonjs/badge/lib/CountBadge.js +8 -8
  18. package/dist/commonjs/banner/lib/Banner.js +1 -1
  19. package/dist/commonjs/button/lib/BaseButton.js +22 -22
  20. package/dist/commonjs/button/lib/DeleteButton.js +1 -1
  21. package/dist/commonjs/button/lib/PrimaryButton.js +2 -2
  22. package/dist/commonjs/button/lib/SecondaryButton.js +2 -2
  23. package/dist/commonjs/button/lib/TertiaryButton.js +15 -15
  24. package/dist/commonjs/button/lib/ToolbarDropdownButton.js +6 -1
  25. package/dist/commonjs/button/lib/ToolbarIconButton.js +6 -1
  26. package/dist/commonjs/button/lib/deprecated_Button.js +2 -2
  27. package/dist/commonjs/card/lib/Card.js +1 -1
  28. package/dist/commonjs/card/lib/CardHeading.js +1 -1
  29. package/dist/commonjs/checkbox/lib/CheckBackground.d.ts +10 -0
  30. package/dist/commonjs/checkbox/lib/CheckBackground.d.ts.map +1 -0
  31. package/dist/commonjs/checkbox/lib/CheckBackground.js +42 -0
  32. package/dist/commonjs/checkbox/lib/Checkbox.d.ts +3 -45
  33. package/dist/commonjs/checkbox/lib/Checkbox.d.ts.map +1 -1
  34. package/dist/commonjs/checkbox/lib/Checkbox.js +10 -204
  35. package/dist/commonjs/checkbox/lib/CheckboxCheck.d.ts +10 -0
  36. package/dist/commonjs/checkbox/lib/CheckboxCheck.d.ts.map +1 -0
  37. package/dist/commonjs/checkbox/lib/CheckboxCheck.js +51 -0
  38. package/dist/commonjs/checkbox/lib/CheckboxContainer.d.ts +13 -0
  39. package/dist/commonjs/checkbox/lib/CheckboxContainer.d.ts.map +1 -0
  40. package/dist/commonjs/checkbox/lib/CheckboxContainer.js +37 -0
  41. package/dist/commonjs/checkbox/lib/CheckboxInput.d.ts +48 -0
  42. package/dist/commonjs/checkbox/lib/CheckboxInput.d.ts.map +1 -0
  43. package/dist/commonjs/checkbox/lib/CheckboxInput.js +59 -0
  44. package/dist/commonjs/checkbox/lib/CheckboxRipple.d.ts +2 -0
  45. package/dist/commonjs/checkbox/lib/CheckboxRipple.d.ts.map +1 -0
  46. package/dist/commonjs/checkbox/lib/CheckboxRipple.js +33 -0
  47. package/dist/commonjs/collection/lib/useCursorListModel.d.ts.map +1 -1
  48. package/dist/commonjs/collection/lib/useListItemAllowChildStrings.d.ts +2 -1
  49. package/dist/commonjs/collection/lib/useListItemAllowChildStrings.d.ts.map +1 -1
  50. package/dist/commonjs/collection/lib/useListItemAllowChildStrings.js +1 -1
  51. package/dist/commonjs/collection/lib/useListRenderItem.js +1 -1
  52. package/dist/commonjs/combobox/lib/hooks/useComboboxInput.d.ts +1 -0
  53. package/dist/commonjs/combobox/lib/hooks/useComboboxInput.d.ts.map +1 -1
  54. package/dist/commonjs/combobox/lib/hooks/useComboboxInput.js +1 -0
  55. package/dist/commonjs/combobox/lib/hooks/useComboboxKeyboardTypeAhead.js +2 -3
  56. package/dist/commonjs/combobox/lib/hooks/useComboboxModel.d.ts.map +1 -1
  57. package/dist/commonjs/combobox/lib/hooks/useComboboxModel.js +1 -2
  58. package/dist/commonjs/common/lib/AccessibleHide.js +1 -1
  59. package/dist/commonjs/common/lib/CanvasProvider.js +1 -1
  60. package/dist/commonjs/common/lib/styles/errorRing.js +2 -2
  61. package/dist/commonjs/common/lib/styles/focusRing.d.ts.map +1 -1
  62. package/dist/commonjs/common/lib/styles/focusRing.js +5 -16
  63. package/dist/commonjs/form-field/lib/Label.js +3 -7
  64. package/dist/commonjs/loading-dots/lib/LoadingDots.js +3 -3
  65. package/dist/commonjs/radio/lib/Radio.js +17 -3
  66. package/dist/commonjs/select/lib/Select.d.ts +2 -1
  67. package/dist/commonjs/select/lib/Select.d.ts.map +1 -1
  68. package/dist/commonjs/select/lib/Select.js +5 -3
  69. package/dist/commonjs/select/lib/hooks/useSelectInput.d.ts +7 -1
  70. package/dist/commonjs/select/lib/hooks/useSelectInput.d.ts.map +1 -1
  71. package/dist/commonjs/select/lib/hooks/useSelectInput.js +45 -4
  72. package/dist/commonjs/select/lib/hooks/useSelectModel.d.ts.map +1 -1
  73. package/dist/commonjs/select/lib/hooks/useSelectModel.js +1 -2
  74. package/dist/commonjs/switch/lib/Switch.js +2 -2
  75. package/dist/commonjs/tabs/lib/TabsItem.js +1 -1
  76. package/dist/commonjs/text/lib/LabelText.js +24 -24
  77. package/dist/commonjs/text/lib/Text.js +15 -15
  78. package/dist/commonjs/text-input/lib/TextInput.js +3 -3
  79. package/dist/commonjs/tooltip/lib/OverflowTooltip.d.ts.map +1 -1
  80. package/dist/commonjs/tooltip/lib/OverflowTooltip.js +3 -2
  81. package/dist/es6/avatar/lib/Avatar.js +1 -1
  82. package/dist/es6/badge/lib/CountBadge.js +7 -7
  83. package/dist/es6/banner/lib/Banner.js +1 -1
  84. package/dist/es6/button/lib/BaseButton.js +22 -22
  85. package/dist/es6/button/lib/DeleteButton.js +1 -1
  86. package/dist/es6/button/lib/PrimaryButton.js +2 -2
  87. package/dist/es6/button/lib/SecondaryButton.js +2 -2
  88. package/dist/es6/button/lib/TertiaryButton.js +15 -15
  89. package/dist/es6/button/lib/ToolbarDropdownButton.js +6 -1
  90. package/dist/es6/button/lib/ToolbarIconButton.js +6 -1
  91. package/dist/es6/button/lib/deprecated_Button.js +2 -2
  92. package/dist/es6/card/lib/Card.js +1 -1
  93. package/dist/es6/card/lib/CardHeading.js +1 -1
  94. package/dist/es6/checkbox/lib/CheckBackground.d.ts +10 -0
  95. package/dist/es6/checkbox/lib/CheckBackground.d.ts.map +1 -0
  96. package/dist/es6/checkbox/lib/CheckBackground.js +20 -0
  97. package/dist/es6/checkbox/lib/Checkbox.d.ts +3 -45
  98. package/dist/es6/checkbox/lib/Checkbox.d.ts.map +1 -1
  99. package/dist/es6/checkbox/lib/Checkbox.js +11 -205
  100. package/dist/es6/checkbox/lib/CheckboxCheck.d.ts +10 -0
  101. package/dist/es6/checkbox/lib/CheckboxCheck.d.ts.map +1 -0
  102. package/dist/es6/checkbox/lib/CheckboxCheck.js +29 -0
  103. package/dist/es6/checkbox/lib/CheckboxContainer.d.ts +13 -0
  104. package/dist/es6/checkbox/lib/CheckboxContainer.d.ts.map +1 -0
  105. package/dist/es6/checkbox/lib/CheckboxContainer.js +15 -0
  106. package/dist/es6/checkbox/lib/CheckboxInput.d.ts +48 -0
  107. package/dist/es6/checkbox/lib/CheckboxInput.d.ts.map +1 -0
  108. package/dist/es6/checkbox/lib/CheckboxInput.js +37 -0
  109. package/dist/es6/checkbox/lib/CheckboxRipple.d.ts +2 -0
  110. package/dist/es6/checkbox/lib/CheckboxRipple.d.ts.map +1 -0
  111. package/dist/es6/checkbox/lib/CheckboxRipple.js +11 -0
  112. package/dist/es6/collection/lib/useCursorListModel.d.ts.map +1 -1
  113. package/dist/es6/collection/lib/useListItemAllowChildStrings.d.ts +2 -1
  114. package/dist/es6/collection/lib/useListItemAllowChildStrings.d.ts.map +1 -1
  115. package/dist/es6/collection/lib/useListItemAllowChildStrings.js +1 -1
  116. package/dist/es6/collection/lib/useListRenderItem.js +1 -1
  117. package/dist/es6/combobox/lib/hooks/useComboboxInput.d.ts +1 -0
  118. package/dist/es6/combobox/lib/hooks/useComboboxInput.d.ts.map +1 -1
  119. package/dist/es6/combobox/lib/hooks/useComboboxInput.js +1 -0
  120. package/dist/es6/combobox/lib/hooks/useComboboxKeyboardTypeAhead.js +2 -3
  121. package/dist/es6/combobox/lib/hooks/useComboboxModel.d.ts.map +1 -1
  122. package/dist/es6/combobox/lib/hooks/useComboboxModel.js +1 -2
  123. package/dist/es6/common/lib/AccessibleHide.js +1 -1
  124. package/dist/es6/common/lib/CanvasProvider.js +1 -1
  125. package/dist/es6/common/lib/styles/errorRing.js +2 -2
  126. package/dist/es6/common/lib/styles/focusRing.d.ts.map +1 -1
  127. package/dist/es6/common/lib/styles/focusRing.js +5 -16
  128. package/dist/es6/form-field/lib/Label.js +3 -7
  129. package/dist/es6/loading-dots/lib/LoadingDots.js +2 -2
  130. package/dist/es6/radio/lib/Radio.js +17 -3
  131. package/dist/es6/select/lib/Select.d.ts +2 -1
  132. package/dist/es6/select/lib/Select.d.ts.map +1 -1
  133. package/dist/es6/select/lib/Select.js +5 -3
  134. package/dist/es6/select/lib/hooks/useSelectInput.d.ts +7 -1
  135. package/dist/es6/select/lib/hooks/useSelectInput.d.ts.map +1 -1
  136. package/dist/es6/select/lib/hooks/useSelectInput.js +43 -5
  137. package/dist/es6/select/lib/hooks/useSelectModel.d.ts.map +1 -1
  138. package/dist/es6/select/lib/hooks/useSelectModel.js +1 -2
  139. package/dist/es6/switch/lib/Switch.js +2 -2
  140. package/dist/es6/tabs/lib/TabsItem.js +1 -1
  141. package/dist/es6/text/lib/LabelText.js +24 -24
  142. package/dist/es6/text/lib/Text.js +15 -15
  143. package/dist/es6/text-input/lib/TextInput.js +3 -3
  144. package/dist/es6/tooltip/lib/OverflowTooltip.d.ts.map +1 -1
  145. package/dist/es6/tooltip/lib/OverflowTooltip.js +3 -2
  146. package/form-field/lib/Label.tsx +10 -10
  147. package/package.json +4 -4
  148. package/select/lib/Select.tsx +51 -4
  149. package/select/lib/hooks/useSelectInput.ts +86 -44
  150. package/select/lib/hooks/useSelectModel.tsx +1 -2
  151. package/text-input/lib/TextInput.tsx +3 -3
  152. package/tooltip/lib/OverflowTooltip.tsx +3 -2
@@ -15,9 +15,9 @@ import {useSelectModel} from './hooks/useSelectModel';
15
15
  import {useSelectCard} from './hooks/useSelectCard';
16
16
  import {useSelectInput} from './hooks/useSelectInput';
17
17
  import {CanvasSystemIcon} from '@workday/design-assets-types';
18
- import {createStyles} from '@workday/canvas-kit-styling';
18
+ import {createStyles, CSProps} from '@workday/canvas-kit-styling';
19
19
 
20
- export interface SelectInputProps extends ExtractProps<typeof TextInput> {
20
+ export interface SelectInputProps extends ExtractProps<typeof TextInput>, CSProps {
21
21
  /**
22
22
  * The Icon to render at the start of the `input`. Use this prop if your options
23
23
  * include icons that you would like to render in the `input` when selected.
@@ -34,11 +34,40 @@ const selectInputStyles = createStyles({
34
34
  },
35
35
  });
36
36
 
37
+ const hiddenSelectStyles = createStyles({
38
+ position: 'absolute',
39
+ top: 0,
40
+ bottom: 0,
41
+ left: 0,
42
+ right: 0,
43
+ opacity: 0,
44
+ cursor: 'default',
45
+ pointerEvents: 'none',
46
+ });
47
+
37
48
  export const SelectInput = createSubcomponent(TextInput)({
38
49
  modelHook: useSelectModel,
39
50
  elemPropsHook: useSelectInput,
40
51
  })<SelectInputProps>(
41
- ({placeholder = 'Choose an option', inputStartIcon, width, ...elemProps}, Element, model) => {
52
+ (
53
+ {
54
+ placeholder = 'Choose an option',
55
+ inputStartIcon,
56
+ error,
57
+ textInputProps,
58
+ disabled,
59
+ width,
60
+ ref,
61
+ onChange,
62
+ onInput,
63
+ onFocus,
64
+ value,
65
+ name,
66
+ ...elemProps
67
+ },
68
+ Element,
69
+ model
70
+ ) => {
42
71
  return (
43
72
  <InputGroup width={width} data-width="ck-formfield-width">
44
73
  {inputStartIcon && model.state.selectedIds.length > 0 && (
@@ -46,11 +75,29 @@ export const SelectInput = createSubcomponent(TextInput)({
46
75
  <SystemIcon icon={inputStartIcon} />
47
76
  </InputGroup.InnerStart>
48
77
  )}
78
+ {/* Hidden input to handle ids */}
79
+ <InputGroup.Input
80
+ error={error}
81
+ disabled={disabled}
82
+ className={hiddenSelectStyles}
83
+ tabIndex={-1}
84
+ aria-hidden={true}
85
+ onChange={onChange}
86
+ onInput={onInput}
87
+ value={value}
88
+ onFocus={onFocus}
89
+ name={name}
90
+ ref={ref}
91
+ />
92
+ {/* Visual input */}
49
93
  <InputGroup.Input
50
94
  as={Element}
95
+ disabled={disabled}
51
96
  placeholder={placeholder}
97
+ error={error}
98
+ {...textInputProps}
52
99
  {...mergeStyles(elemProps, [selectInputStyles])}
53
- ></InputGroup.Input>
100
+ />
54
101
  <InputGroup.InnerEnd position="absolute" pointerEvents="none">
55
102
  <SystemIcon icon={caretDownSmallIcon} />
56
103
  </InputGroup.InnerEnd>
@@ -2,9 +2,9 @@ import React from 'react';
2
2
  import {
3
3
  composeHooks,
4
4
  createElemPropsHook,
5
- useForkRef,
6
5
  useLocalRef,
7
6
  useResizeObserver,
7
+ dispatchInputEvent,
8
8
  } from '@workday/canvas-kit-react/common';
9
9
  import {
10
10
  useComboboxInput,
@@ -18,56 +18,98 @@ import {useSelectModel} from './useSelectModel';
18
18
  * `useSelectInput` extends {@link useComboboxInput useComboboxInput} and {@link useComboboxKeyboardTypeAhead useComboboxKeyboardTypeAhead} and adds type ahead functionality and Select-specific [keyboard support](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/).
19
19
  */
20
20
  export const useSelectInput = composeHooks(
21
- createElemPropsHook(useSelectModel)((model, ref, elemProps: {keySofar?: string} = {}) => {
22
- const {localRef, elementRef} = useLocalRef<HTMLInputElement>(
23
- useForkRef(ref as React.Ref<HTMLElement>, ref)
24
- );
21
+ createElemPropsHook(useSelectModel)(
22
+ (model, ref, elemProps: {keySofar?: string; placeholder?: string} = {}) => {
23
+ const {elementRef} = useLocalRef<HTMLInputElement>(ref as any);
24
+ const textInputRef = React.useRef<HTMLInputElement>(null);
25
25
 
26
- useResizeObserver({
27
- ref: localRef,
28
- onResize: data => {
29
- if (model.state.visibility === 'visible') {
30
- // Width of the Input + 2px border + 8px padding
31
- const calculatedWidth = data.width ? data.width + 42 + 8 : 0;
32
- model.events.setWidth(calculatedWidth);
26
+ // Update the text value of the input
27
+ const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => {
28
+ const value = model.navigation.getItem(event.target.value, model)?.textValue;
29
+ const nativeInputValue = Object.getOwnPropertyDescriptor(
30
+ Object.getPrototypeOf(textInputRef.current),
31
+ 'value'
32
+ );
33
+ if (nativeInputValue && nativeInputValue.set) {
34
+ nativeInputValue.set.call(textInputRef.current, value);
33
35
  }
34
- },
35
- });
36
+ };
36
37
 
37
- return {
38
- onKeyDown(event: React.KeyboardEvent) {
39
- // Prevent the keys from being enter in the input
40
- if (event.key !== 'Tab') {
41
- event.preventDefault();
42
- }
43
-
44
- // Select should open if Spacebar is typed and nothing has been typed AND the menu is hidden
45
- if (
46
- event.key === 'Spacebar' ||
47
- (event.key === ' ' && model.state.visibility === 'hidden' && elemProps?.keySofar === '')
48
- ) {
49
- model.events.show();
50
- }
51
- // if the menu is visible
38
+ useResizeObserver({
39
+ ref: textInputRef,
40
+ onResize: data => {
41
+ if (model.state.visibility === 'visible') {
42
+ // Width of the Input + 2px border + 8px padding
43
+ const calculatedWidth = data.width ? data.width + 42 + 8 : 0;
44
+ model.events.setWidth(calculatedWidth);
45
+ }
46
+ },
47
+ });
48
+ // The intent is if items are loaded after the component is rendered, it will update the input with the value.
49
+ // **Note: We might need to watch for other things or how often we should do this**
50
+ React.useEffect(() => {
52
51
  if (
53
- (event.key === 'Spacebar' || event.key === ' ') &&
54
- model.state.visibility === 'visible'
52
+ model.state.inputRef.current &&
53
+ model.state.items.length > 0 &&
54
+ model.state.selectedIds[0]
55
55
  ) {
56
- // If key so far is empty, they're done typing, select the item where the cursor is located and hide the menu
57
- if (elemProps?.keySofar === '') {
58
- model.events.select({
59
- id: model.state.cursorId,
60
- });
61
- model.events.hide();
56
+ const value = model.navigation.getItem(model.state.selectedIds[0], model).id;
57
+ if (model.state.inputRef.current.value !== value) {
58
+ // Programmatically dispatch an onChange once items are loaded. This account for when a consumer wants an initial selected item and they're loading them from a server.
59
+ dispatchInputEvent(model.state.inputRef.current, value);
62
60
  }
63
61
  }
64
- },
65
- ref: elementRef,
66
- autoComplete: 'off',
67
- defaultValue:
68
- model.navigation.getItem(model.state.selectedIds[0], model).textValue || model.state.value,
69
- } as const;
70
- }),
62
+ // eslint-disable-next-line react-hooks/exhaustive-deps
63
+ }, [model.state.inputRef, model.state.items.length]);
64
+
65
+ return {
66
+ onKeyDown(event: React.KeyboardEvent) {
67
+ // Prevent the keys from being enter in the input
68
+ if (event.key !== 'Tab') {
69
+ event.preventDefault();
70
+ }
71
+
72
+ // Select should open if Spacebar is typed and nothing has been typed AND the menu is hidden
73
+ if (
74
+ event.key === 'Spacebar' ||
75
+ (event.key === ' ' && model.state.visibility === 'hidden' && elemProps?.keySofar === '')
76
+ ) {
77
+ model.events.show();
78
+ }
79
+ // if the menu is visible
80
+ if (
81
+ (event.key === 'Spacebar' || event.key === ' ') &&
82
+ model.state.visibility === 'visible'
83
+ ) {
84
+ // If key so far is empty, they're done typing, select the item where the cursor is located and hide the menu
85
+ if (elemProps?.keySofar === '') {
86
+ model.events.select({
87
+ id: model.state.cursorId,
88
+ });
89
+ model.events.hide();
90
+ }
91
+ }
92
+ },
93
+ onChange: handleOnChange,
94
+ autoComplete: 'off',
95
+ // When the hidden input is focused, we want to show the focus/hover states of the input that sits below it.
96
+ onFocus() {
97
+ textInputRef.current?.focus();
98
+ },
99
+ textInputProps: {
100
+ ref: textInputRef,
101
+ },
102
+ ref: elementRef,
103
+
104
+ // Account for the case where an initial item is selected when the Select first renders
105
+ defaultValue:
106
+ model.state.selectedIds.length > 0 && model.state.items.length > 0
107
+ ? model.navigation.getItem(model.state.selectedIds[0], model).textValue ||
108
+ model.state.value
109
+ : undefined,
110
+ } as const;
111
+ }
112
+ ),
71
113
  useComboboxKeyboardTypeAhead,
72
114
  useComboboxResetCursorToSelected,
73
115
  useComboboxMoveCursorToSelected,
@@ -25,6 +25,5 @@ export const useSelectModel = createModelHook({
25
25
  },
26
26
  contextOverride: useComboboxModel.Context,
27
27
  })(config => {
28
- const model = useComboboxModel(config);
29
- return model;
28
+ return useComboboxModel(config);
30
29
  });
@@ -38,10 +38,10 @@ const StyledTextInput = styled('input')<
38
38
  '&::placeholder': {
39
39
  color: inputColors.placeholder,
40
40
  },
41
- '&:hover': {
41
+ '&:hover, &.hover': {
42
42
  borderColor: inputColors.hoverBorder,
43
43
  },
44
- '&:focus:not([disabled])': {
44
+ '&:focus-visible:not([disabled]), &.focus:not([disabled]), &:focus:not([disabled])': {
45
45
  borderColor: inputColors.focusBorder,
46
46
  boxShadow: `inset 0 0 0 1px ${inputColors.focusBorder}`,
47
47
  outline: 'none',
@@ -68,7 +68,7 @@ const StyledTextInput = styled('input')<
68
68
  },
69
69
  ({theme, error}) => {
70
70
  return {
71
- '&:focus:not([disabled])': {
71
+ '&:focus-visible:not([disabled]), &.focus:not([disabled])': {
72
72
  borderColor: theme.canvas.palette.common.focusOutline,
73
73
  boxShadow: `inset 0 0 0 1px ${theme.canvas.palette.common.focusOutline}`,
74
74
  outline: 'none',
@@ -59,9 +59,10 @@ const isOverflowed = (element: Element) => {
59
59
  const overflowElement = findEllipsisElement(element) || findOverflowElement(element);
60
60
 
61
61
  if (overflowElement) {
62
+ const clientRect = overflowElement.getBoundingClientRect();
62
63
  return (
63
- overflowElement.scrollWidth > overflowElement.clientWidth ||
64
- overflowElement.scrollHeight > overflowElement.clientHeight
64
+ overflowElement.scrollWidth > clientRect.width ||
65
+ overflowElement.scrollHeight > clientRect.height
65
66
  );
66
67
  }
67
68
  return false;