@react-fabric/form 1.0.0-beta.56 → 1.0.0-beta.58

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 (52) hide show
  1. package/css/_field.css +2 -1
  2. package/dist/cjs/form/Form.js +24 -0
  3. package/dist/cjs/index.js +1 -0
  4. package/dist/cjs/input/ArrayInput.js +34 -13
  5. package/dist/cjs/input/AvatarInput.js +17 -10
  6. package/dist/cjs/input/ColorInput.js +1 -0
  7. package/dist/cjs/input/Hidden.js +4 -3
  8. package/dist/cjs/input/Slider.js +2 -2
  9. package/dist/cjs/input/Textarea.js +1 -1
  10. package/dist/cjs/select/DualList.js +16 -8
  11. package/dist/cjs/select/List.js +5 -2
  12. package/dist/cjs/select/Options.js +49 -42
  13. package/dist/cjs/select/Select.js +4 -2
  14. package/dist/cjs/select/useSelect.js +14 -7
  15. package/dist/esm/form/Form.js +26 -3
  16. package/dist/esm/index.js +1 -1
  17. package/dist/esm/input/ArrayInput.js +35 -14
  18. package/dist/esm/input/AvatarInput.js +17 -10
  19. package/dist/esm/input/ColorInput.js +1 -0
  20. package/dist/esm/input/Hidden.js +4 -3
  21. package/dist/esm/input/Slider.js +2 -2
  22. package/dist/esm/input/Textarea.js +1 -1
  23. package/dist/esm/select/DualList.js +16 -8
  24. package/dist/esm/select/List.js +5 -2
  25. package/dist/esm/select/Options.js +49 -42
  26. package/dist/esm/select/Select.js +4 -2
  27. package/dist/esm/select/useSelect.js +14 -7
  28. package/dist/types/form/Form.d.ts +11 -0
  29. package/dist/types/index.d.ts +1 -1
  30. package/dist/types/input/ArrayInput.d.ts +5 -8
  31. package/dist/types/input/AvatarInput.d.ts +6 -1
  32. package/dist/types/input/Hidden.d.ts +5 -1
  33. package/dist/types/select/List.d.ts +1 -1
  34. package/dist/types/select/Options.d.ts +2 -1
  35. package/dist/types/select/Select.d.ts +1 -1
  36. package/dist/types/select/useSelect.d.ts +4 -1
  37. package/dist/types/types/index.d.ts +4 -0
  38. package/package.json +20 -21
  39. package/src/form/Form.tsx +34 -2
  40. package/src/index.ts +1 -1
  41. package/src/input/ArrayInput.tsx +55 -21
  42. package/src/input/AvatarInput.tsx +32 -5
  43. package/src/input/ColorInput.tsx +1 -0
  44. package/src/input/Hidden.tsx +9 -5
  45. package/src/input/Slider.tsx +4 -4
  46. package/src/input/Textarea.tsx +1 -1
  47. package/src/select/DualList.tsx +4 -8
  48. package/src/select/List.tsx +3 -0
  49. package/src/select/Options.tsx +47 -43
  50. package/src/select/Select.tsx +2 -0
  51. package/src/select/useSelect.tsx +15 -6
  52. package/src/types/index.ts +4 -0
@@ -240,39 +240,35 @@ export const DualList = <T extends AnyObject = string>({
240
240
  <div className="self-center mx-2">
241
241
  <ButtonGroup vertical className="outline overflow-hidden bg-base">
242
242
  <Button
243
- rtlFlip
244
243
  size="sm"
245
244
  variant="link"
246
245
  aria-label="scroll to top"
247
246
  onClick={moveAllLeft}
248
- icon={CoreIcons.chevronsLeft}
247
+ icon={{ icon: CoreIcons.chevronsLeft, rtlFlip: true }}
249
248
  disabled={!rightOptions.length}
250
249
  />
251
250
  <Button
252
- rtlFlip
253
251
  size="sm"
254
252
  variant="link"
255
253
  aria-label="scroll up"
256
254
  onClick={moveRightSelected}
257
- icon={CoreIcons.chevronLeft}
255
+ icon={{ icon: CoreIcons.chevronLeft, rtlFlip: true }}
258
256
  disabled={!rightSelected.length}
259
257
  />
260
258
  <Button
261
- rtlFlip
262
259
  size="sm"
263
260
  variant="link"
264
261
  aria-label="scroll down"
265
262
  onClick={moveLeftSelected}
266
- icon={CoreIcons.chevronRight}
263
+ icon={{ icon: CoreIcons.chevronRight, rtlFlip: true }}
267
264
  disabled={!leftSelected.length}
268
265
  />
269
266
  <Button
270
- rtlFlip
271
267
  size="sm"
272
268
  variant="link"
273
269
  aria-label="scroll to bottom"
274
270
  onClick={moveAllRight}
275
- icon={CoreIcons.chevronsRight}
271
+ icon={{ icon: CoreIcons.chevronsRight, rtlFlip: true }}
276
272
  disabled={!leftOptions.length}
277
273
  />
278
274
  </ButtonGroup>
@@ -61,6 +61,7 @@ export const List = <T extends AnyObject = string>({
61
61
  groupProperty,
62
62
  labelProperty,
63
63
  valueProperty,
64
+ infoProperty,
64
65
  sortProperty,
65
66
  multiple,
66
67
  allowCreate,
@@ -106,6 +107,7 @@ export const List = <T extends AnyObject = string>({
106
107
  value,
107
108
  options,
108
109
  multiple,
110
+ alwaysOpen: true,
109
111
  groupProperty,
110
112
  labelProperty,
111
113
  valueProperty,
@@ -320,6 +322,7 @@ export const List = <T extends AnyObject = string>({
320
322
  itemRef={setItemRef}
321
323
  itemProps={makeItemProps}
322
324
  empty={emptyDisplay}
325
+ info={state.activeItem?.[infoProperty ?? "info"]}
323
326
  >
324
327
  {(item, label) => renderer?.(item) ?? label}
325
328
  </Options>
@@ -34,6 +34,7 @@ export const Options = ({
34
34
  className,
35
35
  itemRef,
36
36
  empty,
37
+ info,
37
38
  valueProperty = "id",
38
39
  labelProperty = "label",
39
40
  itemProps,
@@ -41,6 +42,7 @@ export const Options = ({
41
42
  ...rest
42
43
  }: {
43
44
  ref: AnyObject;
45
+ info?: AnyObject;
44
46
  itemRef: AnyObject;
45
47
  style?: AnyObject;
46
48
  items: AnyObject[];
@@ -55,29 +57,48 @@ export const Options = ({
55
57
  return (
56
58
  <div
57
59
  ref={ref}
58
- className={classNames(
59
- "bg-base select-none overflow-x-hidden overflow-y-auto",
60
- className,
61
- )}
60
+ className={classNames("bg-base select-none flex flex-col", className)}
62
61
  style={style}
63
62
  {...rest}
64
63
  >
65
- {items.length === 0 &&
66
- (empty ?? (
67
- <EmptyContent message={<Trans i18nKey="form:select.emptyList" />} />
68
- ))}
69
- {items.map((item, index) => {
70
- if (item.___group___)
71
- return (
72
- <p
73
- key={index}
74
- className="px-2 py-1 text-muted text-xs sticky -top-px z-2 bg-base border-t"
75
- >
76
- {item.label}
77
- </p>
78
- );
64
+ <div className={classNames("overflow-x-hidden overflow-y-auto flex-1")}>
65
+ {items.length === 0 &&
66
+ (empty ?? (
67
+ <EmptyContent message={<Trans i18nKey="form:select.emptyList" />} />
68
+ ))}
69
+ {items.map((item, index) => {
70
+ if (item.___group___)
71
+ return (
72
+ <p
73
+ key={index}
74
+ className="px-2 py-1 text-muted text-xs sticky -top-px z-2 bg-base border-t"
75
+ >
76
+ {item.label}
77
+ </p>
78
+ );
79
+
80
+ if (item.___create___)
81
+ return (
82
+ <div
83
+ role="none"
84
+ key={index}
85
+ tabIndex={active === index ? 0 : -1}
86
+ ref={(el: AnyObject) => itemRef(index, el)}
87
+ data-active={active === index ? true : undefined}
88
+ className={classNames(
89
+ "block text-start truncate px-2 py-1 leading-normal cursor-pointer select-none",
90
+ "data-[active]:bg-primary-200 data-[selected]:bg-primary-600 data-[selected]:text-white data-[active]:data-[selected]:underline",
91
+ )}
92
+ {...itemProps(item)}
93
+ >
94
+ <Trans
95
+ i18nKey="form:select.createOption"
96
+ values={{ query: item.value ?? item }}
97
+ components={[<strong key="t0">query</strong>]}
98
+ />
99
+ </div>
100
+ );
79
101
 
80
- if (item.___create___)
81
102
  return (
82
103
  <div
83
104
  role="none"
@@ -86,36 +107,19 @@ export const Options = ({
86
107
  ref={(el: AnyObject) => itemRef(index, el)}
87
108
  data-active={active === index ? true : undefined}
88
109
  className={classNames(
89
- "block text-start truncate px-2 py-1 leading-normal cursor-pointer select-none",
110
+ "block text-start truncate px-2 py-1 leading-normal cursor-pointer",
90
111
  "data-[active]:bg-primary-200 data-[selected]:bg-primary-600 data-[selected]:text-white data-[active]:data-[selected]:underline",
91
112
  )}
92
113
  {...itemProps(item)}
93
114
  >
94
- <Trans
95
- i18nKey="form:select.createOption"
96
- values={{ query: item.value ?? item }}
97
- components={[<strong key="t0">query</strong>]}
98
- />
115
+ {children(item, item[labelProperty] ?? item)}
99
116
  </div>
100
117
  );
101
-
102
- return (
103
- <div
104
- role="none"
105
- key={index}
106
- tabIndex={active === index ? 0 : -1}
107
- ref={(el: AnyObject) => itemRef(index, el)}
108
- data-active={active === index ? true : undefined}
109
- className={classNames(
110
- "block text-start truncate px-2 py-1 leading-normal cursor-pointer",
111
- "data-[active]:bg-primary-200 data-[selected]:bg-primary-600 data-[selected]:text-white data-[active]:data-[selected]:underline",
112
- )}
113
- {...itemProps(item)}
114
- >
115
- {children(item, item[labelProperty] ?? item)}
116
- </div>
117
- );
118
- })}
118
+ })}
119
+ </div>
120
+ {info && (
121
+ <div className="px-2 py-1 text-sm bg-dimmed text-muted">{info}</div>
122
+ )}
119
123
  </div>
120
124
  );
121
125
  };
@@ -70,6 +70,7 @@ export const Select = <T extends AnyObject = string>({
70
70
  labelProperty = "label" as AnyObject,
71
71
  valueProperty = "id" as AnyObject,
72
72
  sortProperty,
73
+ infoProperty,
73
74
  multiple,
74
75
  searchable,
75
76
  allowCreate,
@@ -357,6 +358,7 @@ export const Select = <T extends AnyObject = string>({
357
358
  itemRef={setItemRef}
358
359
  itemProps={makeItemProps}
359
360
  empty={emptyDisplay}
361
+ info={state.activeItem?.[infoProperty ?? "info"]}
360
362
  >
361
363
  {(item, label) => renderer?.(item) ?? label}
362
364
  </Options>
@@ -65,6 +65,7 @@ interface State {
65
65
  open: boolean;
66
66
  loading: boolean;
67
67
  activeIndex: number | null;
68
+ activeItem: AnyObject;
68
69
  selectedIndex: number | null;
69
70
  value: AnyObject;
70
71
  // filter
@@ -76,8 +77,9 @@ interface State {
76
77
  export const useSelect = ({
77
78
  options = EMPTY_ARRAY,
78
79
  value,
79
- defaultOpen = false,
80
80
  autoComplete,
81
+ alwaysOpen = false,
82
+ defaultOpen = false,
81
83
  multiple = false,
82
84
  allowCreate = false,
83
85
  groupProperty = "",
@@ -93,6 +95,7 @@ export const useSelect = ({
93
95
  value?: AnyObject;
94
96
  options?: AnyObject[];
95
97
  multiple?: boolean;
98
+ alwaysOpen?: boolean;
96
99
  defaultOpen?: boolean;
97
100
  allowCreate?: boolean;
98
101
  groupProperty?: AnyObject;
@@ -149,12 +152,16 @@ export const useSelect = ({
149
152
  };
150
153
  }
151
154
  if (action.type === "close") {
152
- return { ...state, activeIndex: null, open: false };
155
+ return { ...state, activeIndex: null, activeItem: null, open: false };
153
156
  }
154
157
  if (action.type === "active" && state.open) {
155
158
  if (autoComplete && action.index !== null)
156
159
  state.query = state.items[action.index];
157
- return { ...state, activeIndex: action.index };
160
+ return {
161
+ ...state,
162
+ activeIndex: action.index,
163
+ activeItem: state.items[action.index ?? -1],
164
+ };
158
165
  }
159
166
  if (action.type === "setValue") {
160
167
  return {
@@ -170,6 +177,7 @@ export const useSelect = ({
170
177
  ...state,
171
178
  value: state.emptyValue,
172
179
  activeIndex: null,
180
+ activeItem: null,
173
181
  selectedIndex: autoComplete
174
182
  ? state.multiple
175
183
  ? action.value?.length
@@ -192,7 +200,7 @@ export const useSelect = ({
192
200
  newState.value = action.value;
193
201
  }
194
202
  }
195
- if (!state.multiple) newState.open = false;
203
+ if (!state.multiple) newState.open = alwaysOpen;
196
204
  fireChange(newState.value);
197
205
  return newState;
198
206
  }
@@ -261,9 +269,10 @@ export const useSelect = ({
261
269
  {
262
270
  multiple,
263
271
  emptyValue,
264
- open: defaultOpen,
272
+ open: alwaysOpen || defaultOpen,
265
273
  loading: false,
266
274
  activeIndex: null,
275
+ activeItem: null,
267
276
  selectedIndex: null,
268
277
  value: emptyValue,
269
278
  // filter
@@ -407,7 +416,7 @@ export const useSelect = ({
407
416
  }, []);
408
417
 
409
418
  const setActiveIndex = useCallback((index: number | null) => {
410
- dispatch({ type: "active", index });
419
+ index && index > -1 && dispatch({ type: "active", index });
411
420
  }, []);
412
421
 
413
422
  return {
@@ -154,6 +154,10 @@ export interface BaseSelectProps<T extends AnyObject = string> {
154
154
  * value property name
155
155
  */
156
156
  valueProperty?: keyof T;
157
+ /**
158
+ * value property name
159
+ */
160
+ infoProperty?: keyof T;
157
161
  /**
158
162
  * value property name
159
163
  */