@mirohq/design-system-base-input 0.1.0-forms.1 → 0.1.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/main.js CHANGED
@@ -2,137 +2,226 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var React = require('react');
5
7
  var designSystemUtils = require('@mirohq/design-system-utils');
6
- var designSystemStitches = require('@mirohq/design-system-stitches');
8
+ var designSystemUsePress = require('@mirohq/design-system-use-press');
9
+ var interactions = require('@react-aria/interactions');
10
+ var utils = require('@react-aria/utils');
7
11
  var designSystemPrimitive = require('@mirohq/design-system-primitive');
12
+ var designSystemStitches = require('@mirohq/design-system-stitches');
13
+ var designSystemIcons = require('@mirohq/design-system-icons');
14
+ var designSystemBaseTextField = require('@mirohq/design-system-base-text-field');
15
+ var designSystemBaseButton = require('@mirohq/design-system-base-button');
16
+ var designSystemStyles = require('@mirohq/design-system-styles');
17
+ var designSystemUseAriaDisabled = require('@mirohq/design-system-use-aria-disabled');
18
+ var designSystemTooltip = require('@mirohq/design-system-tooltip');
19
+ var designSystemBaseIcon = require('@mirohq/design-system-base-icon');
20
+ var designSystemUseLayoutEffect = require('@mirohq/design-system-use-layout-effect');
21
+
22
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
23
+
24
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
8
25
 
9
- const styles = {
26
+ const StyledIconSlot = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
27
+ order: 1,
28
+ alignContent: "center",
29
+ display: "flex",
30
+ justifyContent: "center",
31
+ color: "$icon-neutrals-subtle",
32
+ "& svg, & img": {
33
+ pointerEvents: "none"
34
+ },
10
35
  variants: {
11
- idle: {
12
- background: "$background-neutrals-container",
13
- border: "1px solid $border-neutrals",
14
- borderRadius: "$50",
15
- fontSize: "$200",
16
- lineHeight: "1.5"
17
- },
18
- focused: {
19
- boxShadow: "$focus-controls",
20
- borderColor: "$border-neutrals"
21
- },
22
- hovered: {
23
- borderColor: "$border-primary-hover"
24
- },
25
- readOnly: {
26
- background: "$background-neutrals-disabled",
27
- color: "$text-neutrals-subtle"
28
- },
29
36
  disabled: {
30
- background: "$background-neutrals-disabled"
31
- },
32
- invalid: {
33
- idle: {
34
- borderColor: "$border-danger"
35
- },
36
- focused: {
37
- borderColor: "$border-danger",
38
- boxShadow: "$focus-controls-error"
39
- },
40
- hovered: {
41
- borderColor: "$border-danger-hover"
42
- }
43
- },
44
- valid: {
45
- idle: {
46
- borderColor: "$border-success"
47
- },
48
- focused: {
49
- borderColor: "$border-success",
50
- boxShadow: "$focus-controls-success"
51
- },
52
- hovered: {
53
- borderColor: "$border-success-hover"
37
+ true: {
38
+ "& svg": {
39
+ color: "$icon-neutrals-disabled"
40
+ }
54
41
  }
55
42
  }
43
+ }
44
+ });
45
+
46
+ const StyledActionButton = designSystemStitches.styled(designSystemBaseButton.BaseButton, {
47
+ backgroundColor: "transparent",
48
+ color: "$icon-neutrals-subtle",
49
+ display: "flex",
50
+ justifyContent: "center",
51
+ order: 3,
52
+ padding: "6px",
53
+ square: "$7",
54
+ "& svg:not([data-icon-component]), & img:not([data-icon-component])": {
55
+ square: "$icon-200",
56
+ "--svg-stroke-width": "$stroke-width$thin"
57
+ },
58
+ ...designSystemStyles.focus.css({
59
+ boxShadow: "$focus-small"
60
+ }),
61
+ "&:hover": {
62
+ backgroundColor: "$background-neutrals-subtle-hover"
63
+ },
64
+ "&:active, &[data-pressed]": {
65
+ backgroundColor: "$background-neutrals-subtle-active"
56
66
  },
57
- base: {
58
- placeholder: {
59
- color: "$text-neutrals-subtle"
67
+ variants: {
68
+ readOnlyAppearance: {
69
+ true: {
70
+ "& svg[data-icon-component], & img[data-icon-component]": {
71
+ color: "$icon-neutrals-subtle"
72
+ }
73
+ }
60
74
  },
61
- disabled: {
62
- caretColor: "transparent",
63
- "&, &::placeholder": {
64
- color: "$text-neutrals-disabled",
65
- "-webkit-text-fill-color": "$colors$text-neutrals-disabled"
66
- },
67
- "&:selection": {
68
- background: "transparent"
75
+ disableAppearance: {
76
+ true: {
77
+ color: "$icon-neutrals-disabled"
69
78
  }
70
79
  }
71
80
  }
72
- };
81
+ });
73
82
 
74
- const keyboardEventHandler = (e) => {
75
- if (e.key !== "Tab") {
76
- e.preventDefault();
77
- }
78
- };
79
- const useAriaDisabled = (props, ariaDisabled) => {
80
- if (!designSystemUtils.booleanify(ariaDisabled)) {
81
- return props;
83
+ const StyledIconExclamationPointCircle = designSystemStitches.styled(
84
+ designSystemIcons.IconExclamationPointCircle,
85
+ {
86
+ color: "$icon-danger"
82
87
  }
83
- const formattedProps = designSystemUtils.removeEventProps(props, [
84
- "onFocus",
85
- "onBlur",
86
- "onPointerMove"
87
- ]);
88
- formattedProps.onKeyDown = keyboardEventHandler;
89
- formattedProps.onKeyUp = keyboardEventHandler;
90
- return formattedProps;
91
- };
92
-
93
- const FloatingLabel = designSystemStitches.styled(designSystemPrimitive.Primitive.label, {
94
- transitionProperty: "transform, left, top, font-size",
95
- transitionDuration: "200ms",
96
- transitionTimingFunction: "cubic-bezier(0, 0, 0.2, 1)",
88
+ );
89
+ const StyledIconCheckMark = designSystemStitches.styled(designSystemIcons.IconCheckMark, {
90
+ color: "$icon-success"
91
+ });
92
+ const StyledValidityBox = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
93
+ order: 3,
94
+ display: "flex",
95
+ alignItems: "center",
96
+ padding: "6px"
97
+ });
98
+ const StyledBaseInput = designSystemStitches.styled("div", {
99
+ position: "relative",
100
+ alignItems: "center",
101
+ display: "inline-flex",
102
+ height: "max-content",
103
+ boxSizing: "border-box",
104
+ width: "100%",
105
+ ...designSystemBaseTextField.styles.variants.idle,
97
106
  variants: {
98
- floating: {
99
- true: {
100
- transform: "translate(2px, -8px)",
101
- fontSize: "$150",
102
- lineHeight: 1.5,
103
- height: "1.5em",
104
- color: "$text-neutrals-subtle",
105
- padding: "0 2px",
106
- backgroundColor: "$background-neutrals-container"
107
- },
108
- false: {
109
- transform: "translate(0, 0)",
110
- fontSize: "$200",
111
- lineHeight: 1.5,
112
- height: "1.5em",
113
- ...styles.base.placeholder
114
- }
107
+ hovered: {
108
+ true: {},
109
+ false: {}
110
+ },
111
+ focused: {
112
+ true: designSystemBaseTextField.styles.variants.focused,
113
+ false: {}
114
+ },
115
+ valid: {
116
+ true: {},
117
+ false: {}
118
+ },
119
+ readOnly: {
120
+ true: designSystemBaseTextField.styles.variants.readOnly,
121
+ false: {}
122
+ },
123
+ disabled: {
124
+ true: designSystemBaseTextField.styles.variants.disabled,
125
+ false: {}
126
+ },
127
+ ariaDisabled: {
128
+ true: designSystemBaseTextField.styles.variants.disabled,
129
+ false: {}
115
130
  },
116
131
  size: {
117
- large: {},
118
- "x-large": {}
132
+ large: {
133
+ height: "$10",
134
+ padding: "0 $100 ",
135
+ ["& ".concat(StyledIconSlot)]: {
136
+ paddingRight: "$50"
137
+ },
138
+ ["& ".concat(StyledActionButton, ", & ").concat(StyledValidityBox)]: {
139
+ marginLeft: "$50"
140
+ },
141
+ ["& ".concat(StyledValidityBox)]: {
142
+ paddingRight: "6px"
143
+ }
144
+ },
145
+ "x-large": {
146
+ height: "$12",
147
+ padding: "0 $150",
148
+ ["& ".concat(StyledIconSlot)]: {
149
+ paddingRight: "$100"
150
+ },
151
+ ["& ".concat(StyledActionButton, ", & ").concat(StyledValidityBox)]: {
152
+ marginLeft: "$100"
153
+ },
154
+ ["& ".concat(StyledValidityBox)]: {
155
+ paddingRight: "6px"
156
+ }
157
+ }
119
158
  }
120
159
  },
121
160
  compoundVariants: [
161
+ /** Idle states */
122
162
  {
123
- size: "large",
124
- floating: false,
125
- css: {
126
- top: "7px"
127
- }
163
+ valid: false,
164
+ readOnly: false,
165
+ disabled: false,
166
+ ariaDisabled: false,
167
+ css: designSystemBaseTextField.styles.variants.invalid.idle
128
168
  },
129
169
  {
130
- size: "x-large",
131
- floating: false,
170
+ valid: true,
171
+ readOnly: false,
172
+ disabled: false,
173
+ ariaDisabled: false,
174
+ css: designSystemBaseTextField.styles.variants.valid.idle
175
+ },
176
+ /** Focus States */
177
+ {
178
+ focused: true,
179
+ readOnly: false,
132
180
  css: {
133
- top: "11px",
134
- left: "$200"
181
+ borderColor: designSystemBaseTextField.styles.variants.focused.borderColor
135
182
  }
183
+ },
184
+ {
185
+ focused: true,
186
+ readOnly: false,
187
+ valid: false,
188
+ disabled: false,
189
+ ariaDisabled: false,
190
+ css: designSystemBaseTextField.styles.variants.invalid.focused
191
+ },
192
+ {
193
+ focused: true,
194
+ readOnly: false,
195
+ valid: true,
196
+ disabled: false,
197
+ ariaDisabled: false,
198
+ css: designSystemBaseTextField.styles.variants.valid.focused
199
+ },
200
+ /** Hover states */
201
+ {
202
+ hovered: true,
203
+ disabled: false,
204
+ ariaDisabled: false,
205
+ readOnly: false,
206
+ css: designSystemBaseTextField.styles.variants.hovered
207
+ },
208
+ {
209
+ hovered: true,
210
+ focused: false,
211
+ valid: false,
212
+ readOnly: false,
213
+ disabled: false,
214
+ ariaDisabled: false,
215
+ css: designSystemBaseTextField.styles.variants.invalid.hovered
216
+ },
217
+ {
218
+ hovered: true,
219
+ focused: false,
220
+ valid: true,
221
+ readOnly: false,
222
+ disabled: false,
223
+ ariaDisabled: false,
224
+ css: designSystemBaseTextField.styles.variants.valid.hovered
136
225
  }
137
226
  ],
138
227
  defaultVariants: {
@@ -140,20 +229,272 @@ const FloatingLabel = designSystemStitches.styled(designSystemPrimitive.Primitiv
140
229
  }
141
230
  });
142
231
 
143
- const inputSymbol = Symbol.for("input");
144
- const isInputComponent = (inputComponent) => {
145
- var _a, _b;
146
- return Boolean(
147
- (_b = inputComponent[inputSymbol]) != null ? _b : (
148
- // @ts-expect-error
149
- (_a = inputComponent == null ? void 0 : inputComponent.type) == null ? void 0 : _a[inputSymbol]
150
- )
232
+ const disabledAndReadonlySelectors = ':read-only, :disabled, [aria-disabled="true"], [data-disabled]';
233
+ const StyledInput = designSystemStitches.styled(designSystemPrimitive.Primitive.input, {
234
+ all: "unset",
235
+ background: "transparent",
236
+ color: "$text-neutrals",
237
+ width: "100%",
238
+ borderRadius: "$50",
239
+ order: 2,
240
+ padding: "0 $50",
241
+ height: "100%",
242
+ "&::placeholder": {
243
+ fontStyle: "italic"
244
+ },
245
+ ["&:not(".concat(disabledAndReadonlySelectors, ")::placeholder")]: designSystemBaseTextField.styles.base.placeholder,
246
+ "&:read-only": {
247
+ color: designSystemBaseTextField.styles.variants.readOnly.color
248
+ },
249
+ "&:disabled, &[aria-disabled=true], &[data-disabled]": designSystemBaseTextField.styles.base.disabled
250
+ });
251
+
252
+ const InputContext = React.createContext({});
253
+ const InputProvider = ({
254
+ children,
255
+ disabled,
256
+ "aria-disabled": ariaDisabled,
257
+ readOnly,
258
+ required,
259
+ valid,
260
+ ...restProps
261
+ }) => {
262
+ const actionButtonRef = React.useRef(null);
263
+ const inputRef = React.useRef(null);
264
+ const [focused, setFocused] = React.useState(false);
265
+ const [hovered, setHovered] = React.useState(false);
266
+ const [hasIconSlot, setHasIconSlot] = React.useState(false);
267
+ const editable = !designSystemUtils.booleanify(disabled) && !designSystemUtils.booleanify(ariaDisabled) && !designSystemUtils.booleanify(readOnly);
268
+ return /* @__PURE__ */ jsxRuntime.jsx(
269
+ InputContext.Provider,
270
+ {
271
+ value: {
272
+ ...restProps,
273
+ setFocused,
274
+ setHovered,
275
+ setHasIconSlot,
276
+ hasIconSlot,
277
+ hovered,
278
+ focused,
279
+ disabled,
280
+ "aria-disabled": ariaDisabled,
281
+ readOnly,
282
+ editable,
283
+ inputRef,
284
+ actionButtonRef,
285
+ required,
286
+ valid
287
+ },
288
+ children
289
+ }
151
290
  );
152
291
  };
292
+ const useInputContext = () => React.useContext(InputContext);
293
+
294
+ const Input = React__default["default"].forwardRef(
295
+ ({
296
+ id,
297
+ "aria-describedby": ariaDescribedBy,
298
+ "aria-invalid": ariaInvalid,
299
+ ...restProps
300
+ }, forwardRef) => {
301
+ const {
302
+ "aria-disabled": ariaDisabled,
303
+ disabled,
304
+ setFocused,
305
+ inputRef,
306
+ required,
307
+ readOnly,
308
+ onChange
309
+ } = useInputContext();
310
+ const { onBlur, onFocus, ...elementProps } = designSystemUseAriaDisabled.useAriaDisabled({
311
+ ...restProps,
312
+ ariaDisabled
313
+ });
314
+ const onFocusHandler = React__default["default"].useCallback(
315
+ (e) => {
316
+ setFocused(true);
317
+ onFocus == null ? void 0 : onFocus(e);
318
+ },
319
+ [setFocused, onFocus]
320
+ );
321
+ const onBlurHandler = React__default["default"].useCallback(
322
+ (e) => {
323
+ setFocused(false);
324
+ onBlur == null ? void 0 : onBlur(e);
325
+ },
326
+ [setFocused, onBlur]
327
+ );
328
+ return /* @__PURE__ */ jsxRuntime.jsx(
329
+ StyledInput,
330
+ {
331
+ ...elementProps,
332
+ id,
333
+ readOnly,
334
+ "aria-describedby": ariaDescribedBy,
335
+ "aria-invalid": ariaInvalid,
336
+ disabled: disabled === true || void 0,
337
+ required: required === true || void 0,
338
+ onFocus: onFocusHandler,
339
+ onBlur: onBlurHandler,
340
+ onChange,
341
+ ref: designSystemUtils.mergeRefs([inputRef, forwardRef])
342
+ }
343
+ );
344
+ }
345
+ );
346
+
347
+ const ActionButton = React__default["default"].forwardRef(({ "aria-label": ariaLabel, label, children, ...restProps }, forwardRef) => {
348
+ const {
349
+ valid,
350
+ hovered,
351
+ editable,
352
+ "aria-disabled": ariaDisabled,
353
+ disabled,
354
+ readOnly,
355
+ actionButtonRef
356
+ } = useInputContext();
357
+ const showInputSlot = valid === void 0 || designSystemUtils.booleanify(hovered);
358
+ let formattedChildren = children;
359
+ formattedChildren = designSystemUtils.addPropsToChildren(children, designSystemBaseIcon.isIconComponent, {
360
+ "aria-hidden": true
361
+ });
362
+ const hasPressEvent = Object.keys(restProps).some(
363
+ (key) => key.startsWith("onPress")
364
+ );
365
+ const customDisabled = restProps.disabled;
366
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: showInputSlot && /* @__PURE__ */ jsxRuntime.jsxs(designSystemTooltip.Tooltip, { children: [
367
+ /* @__PURE__ */ jsxRuntime.jsx(designSystemTooltip.Tooltip.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
368
+ StyledActionButton,
369
+ {
370
+ type: "button",
371
+ ...restProps,
372
+ "aria-label": ariaLabel != null ? ariaLabel : label,
373
+ disabled: hasPressEvent ? customDisabled : customDisabled != null ? customDisabled : !editable,
374
+ disableAppearance: hasPressEvent ? !designSystemUtils.booleanify(readOnly) && customDisabled : designSystemUtils.booleanify(disabled != null ? disabled : ariaDisabled),
375
+ readOnlyAppearance: readOnly,
376
+ ref: designSystemUtils.mergeRefs([forwardRef, actionButtonRef]),
377
+ children: formattedChildren
378
+ }
379
+ ) }),
380
+ /* @__PURE__ */ jsxRuntime.jsx(designSystemTooltip.Tooltip.Content, { children: label })
381
+ ] }) });
382
+ });
383
+
384
+ const IconSlot = React__default["default"].forwardRef(({ children, ...restProps }, forwardRef) => {
385
+ const {
386
+ "aria-disabled": ariaDisabled,
387
+ disabled,
388
+ setHasIconSlot
389
+ } = useInputContext();
390
+ const formattedChildren = designSystemUtils.addPropsToChildren(children, designSystemBaseIcon.isIconComponent, {
391
+ size: "small",
392
+ weight: "thin",
393
+ "aria-hidden": true
394
+ });
395
+ designSystemUseLayoutEffect.useLayoutEffect(() => {
396
+ setHasIconSlot(true);
397
+ return () => setHasIconSlot(false);
398
+ }, [setHasIconSlot]);
399
+ return /* @__PURE__ */ jsxRuntime.jsx(
400
+ StyledIconSlot,
401
+ {
402
+ ...restProps,
403
+ disabled: designSystemUtils.booleanify(disabled != null ? disabled : ariaDisabled),
404
+ ref: forwardRef,
405
+ children: formattedChildren
406
+ }
407
+ );
408
+ });
409
+ IconSlot.displayName = "IconSlot";
410
+
411
+ const Root = React__default["default"].forwardRef(({ children, size, ...restProps }, forwardRef) => {
412
+ const ref = React.useRef(null);
413
+ const {
414
+ valid,
415
+ "aria-disabled": ariaDisabled,
416
+ disabled,
417
+ readOnly,
418
+ focused,
419
+ setHovered,
420
+ inputRef,
421
+ actionButtonRef,
422
+ setFocused
423
+ } = useInputContext();
424
+ const { hoverProps, isHovered: hovered } = interactions.useHover({
425
+ onHoverChange: setHovered
426
+ });
427
+ const { pressProps } = designSystemUsePress.usePress({
428
+ onPressStart: (e) => {
429
+ const { target } = e.originalEvent;
430
+ const shouldPrevent = document.activeElement === inputRef.current && target !== inputRef.current;
431
+ if (shouldPrevent) {
432
+ e.originalEvent.preventDefault();
433
+ }
434
+ },
435
+ onPressEnd: (e) => {
436
+ var _a, _b;
437
+ const { target } = e.originalEvent;
438
+ const isActionButton = target === actionButtonRef.current || ((_a = actionButtonRef.current) == null ? void 0 : _a.contains(target)) === true;
439
+ const shouldFocusInput = !isActionButton && !designSystemUtils.booleanify(disabled) && !designSystemUtils.booleanify(focused);
440
+ if (shouldFocusInput) {
441
+ (_b = inputRef.current) == null ? void 0 : _b.focus();
442
+ setFocused(true);
443
+ }
444
+ },
445
+ preventFocusOnPress: "auto"
446
+ });
447
+ const ariaDisabledOrDisabled = designSystemUtils.booleanify(ariaDisabled) || designSystemUtils.booleanify(disabled);
448
+ const showValidityIcon = !designSystemUtils.booleanify(readOnly) && !ariaDisabledOrDisabled && !hovered && !focused && valid !== void 0;
449
+ const ValidIcon = valid === true ? StyledIconCheckMark : StyledIconExclamationPointCircle;
450
+ return /* @__PURE__ */ jsxRuntime.jsxs(
451
+ StyledBaseInput,
452
+ {
453
+ ...utils.mergeProps(restProps, hoverProps, pressProps),
454
+ "data-invalid": designSystemUtils.booleanishAttrValue(valid === false),
455
+ "data-valid": designSystemUtils.booleanishAttrValue(valid === true),
456
+ "data-form-element": "input",
457
+ ref: designSystemUtils.mergeRefs([ref, forwardRef]),
458
+ size,
459
+ hovered,
460
+ focused,
461
+ valid,
462
+ disabled: designSystemUtils.booleanify(disabled),
463
+ ariaDisabled: designSystemUtils.booleanify(ariaDisabled),
464
+ readOnly: designSystemUtils.booleanify(readOnly),
465
+ children: [
466
+ children,
467
+ showValidityIcon && /* @__PURE__ */ jsxRuntime.jsx(StyledValidityBox, { children: /* @__PURE__ */ jsxRuntime.jsx(ValidIcon, { size: "small", weight: "thin" }) })
468
+ ]
469
+ }
470
+ );
471
+ });
472
+ const BaseInput = React__default["default"].forwardRef(
473
+ ({
474
+ "aria-disabled": ariaDisabled,
475
+ disabled,
476
+ valid,
477
+ readOnly,
478
+ required,
479
+ onChange,
480
+ ...restProps
481
+ }, forwardRef) => /* @__PURE__ */ jsxRuntime.jsx(
482
+ InputProvider,
483
+ {
484
+ valid,
485
+ disabled,
486
+ "aria-disabled": ariaDisabled,
487
+ readOnly,
488
+ required,
489
+ onChange,
490
+ children: /* @__PURE__ */ jsxRuntime.jsx(Root, { ...restProps, ref: forwardRef })
491
+ }
492
+ )
493
+ );
494
+ BaseInput.Input = Input;
495
+ BaseInput.ActionButton = ActionButton;
496
+ BaseInput.IconSlot = IconSlot;
153
497
 
154
- exports.FloatingLabel = FloatingLabel;
155
- exports.inputSymbol = inputSymbol;
156
- exports.isInputComponent = isInputComponent;
157
- exports.styles = styles;
158
- exports.useAriaDisabled = useAriaDisabled;
498
+ exports.BaseInput = BaseInput;
499
+ exports.useInputContext = useInputContext;
159
500
  //# sourceMappingURL=main.js.map