@dxos/react-ui 0.1.2 → 0.1.4

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 (77) hide show
  1. package/dist/src/components/AlertDialog/AlertDialog.js +1 -1
  2. package/dist/src/components/Avatar/Avatar.d.ts +1 -1
  3. package/dist/src/components/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/src/components/Avatar/Avatar.stories.d.ts +1 -1
  5. package/dist/src/components/Button/Button.d.ts +1 -1
  6. package/dist/src/components/Button/Button.d.ts.map +1 -1
  7. package/dist/src/components/Button/Button.stories.d.ts +1 -1
  8. package/dist/src/components/Heading/Heading.d.ts +4 -1
  9. package/dist/src/components/Heading/Heading.d.ts.map +1 -1
  10. package/dist/src/components/Heading/Heading.stories.d.ts +4 -1
  11. package/dist/src/components/Heading/Heading.stories.d.ts.map +1 -1
  12. package/dist/src/components/Input/BarePinInput.d.ts +313 -0
  13. package/dist/src/components/Input/BarePinInput.d.ts.map +1 -0
  14. package/dist/src/components/Input/BarePinInput.js +62 -0
  15. package/dist/src/components/Input/BarePinInput.js.map +1 -0
  16. package/dist/src/components/Input/BareTextInput.d.ts +5 -0
  17. package/dist/src/components/Input/BareTextInput.d.ts.map +1 -0
  18. package/dist/src/components/Input/BareTextInput.js +22 -0
  19. package/dist/src/components/Input/BareTextInput.js.map +1 -0
  20. package/dist/src/components/Input/Input.d.ts +3 -16
  21. package/dist/src/components/Input/Input.d.ts.map +1 -1
  22. package/dist/src/components/Input/Input.js +22 -10
  23. package/dist/src/components/Input/Input.js.map +1 -1
  24. package/dist/src/components/Input/Input.stories.d.ts +7 -3
  25. package/dist/src/components/Input/Input.stories.d.ts.map +1 -1
  26. package/dist/src/components/Input/Input.stories.js +15 -2
  27. package/dist/src/components/Input/Input.stories.js.map +1 -1
  28. package/dist/src/components/Input/InputProps.d.ts +17 -0
  29. package/dist/src/components/Input/InputProps.d.ts.map +1 -0
  30. package/dist/src/components/Input/InputProps.js +6 -0
  31. package/dist/src/components/Input/InputProps.js.map +1 -0
  32. package/dist/src/hooks/index.d.ts +2 -0
  33. package/dist/src/hooks/index.d.ts.map +1 -1
  34. package/dist/src/hooks/index.js +2 -0
  35. package/dist/src/hooks/index.js.map +1 -1
  36. package/dist/src/hooks/useForwardedRef.d.ts +2 -0
  37. package/dist/src/hooks/useForwardedRef.d.ts.map +1 -0
  38. package/dist/src/hooks/useForwardedRef.js +24 -0
  39. package/dist/src/hooks/useForwardedRef.js.map +1 -0
  40. package/dist/src/hooks/useIsFocused.d.ts +3 -0
  41. package/dist/src/hooks/useIsFocused.d.ts.map +1 -0
  42. package/dist/src/hooks/useIsFocused.js +34 -0
  43. package/dist/src/hooks/useIsFocused.js.map +1 -0
  44. package/dist/src/plugin.d.ts.map +1 -1
  45. package/dist/src/plugin.js +9 -1
  46. package/dist/src/plugin.js.map +1 -1
  47. package/dist/src/styles/focus.d.ts +1 -0
  48. package/dist/src/styles/focus.d.ts.map +1 -1
  49. package/dist/src/styles/focus.js +2 -1
  50. package/dist/src/styles/focus.js.map +1 -1
  51. package/dist/src/styles/index.d.ts +1 -0
  52. package/dist/src/styles/index.d.ts.map +1 -1
  53. package/dist/src/styles/index.js +1 -0
  54. package/dist/src/styles/index.js.map +1 -1
  55. package/dist/src/styles/input.d.ts +11 -0
  56. package/dist/src/styles/input.d.ts.map +1 -0
  57. package/dist/src/styles/input.js +24 -0
  58. package/dist/src/styles/input.js.map +1 -0
  59. package/dist/src/styles/shimmer.d.ts +2 -0
  60. package/dist/src/styles/shimmer.d.ts.map +1 -0
  61. package/dist/src/styles/shimmer.js +8 -0
  62. package/dist/src/styles/shimmer.js.map +1 -0
  63. package/package.json +3 -2
  64. package/src/components/AlertDialog/AlertDialog.tsx +1 -1
  65. package/src/components/Input/BarePinInput.tsx +62 -0
  66. package/src/components/Input/BareTextInput.tsx +31 -0
  67. package/src/components/Input/Input.stories.tsx +18 -1
  68. package/src/components/Input/Input.tsx +33 -54
  69. package/src/components/Input/InputProps.ts +23 -0
  70. package/src/hooks/index.ts +2 -0
  71. package/src/hooks/useForwardedRef.ts +22 -0
  72. package/src/hooks/useIsFocused.ts +38 -0
  73. package/src/plugin.ts +9 -1
  74. package/src/styles/focus.ts +3 -0
  75. package/src/styles/index.ts +1 -0
  76. package/src/styles/input.ts +47 -0
  77. package/src/styles/shimmer.ts +6 -0
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2022 DXOS.org
4
+ //
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.staticInput = exports.defaultInput = void 0;
10
+ const classnames_1 = __importDefault(require("classnames"));
11
+ const disabled_1 = require("./disabled");
12
+ const focus_1 = require("./focus");
13
+ const hover_1 = require("./hover");
14
+ const text_1 = require("./text");
15
+ const valence_1 = require("./valence");
16
+ const defaultInput = ({ disabled, validationValence }) => {
17
+ return (0, classnames_1.default)(focus_1.defaultFocus, text_1.defaultPlaceholder, (0, hover_1.defaultHover)({ disabled }), 'bg-white/50 border text-neutral-900 text-sm rounded-lg dark:bg-neutral-700/50 dark:text-white', (0, valence_1.valenceInputBorder)(validationValence), disabled && disabled_1.defaultDisabled);
18
+ };
19
+ exports.defaultInput = defaultInput;
20
+ const staticInput = ({ disabled, focused, validationValence }) => {
21
+ return (0, classnames_1.default)(text_1.defaultPlaceholder, 'bg-white/50 border text-neutral-900 text-sm rounded-lg dark:bg-neutral-700/50 dark:text-white', (0, valence_1.valenceInputBorder)(validationValence), disabled && disabled_1.defaultDisabled, focused && focus_1.staticFocus);
22
+ };
23
+ exports.staticInput = staticInput;
24
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../src/styles/input.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,0BAA0B;AAC1B,EAAE;;;;;;AAEF,4DAA4B;AAG5B,yCAA6C;AAC7C,mCAAoD;AACpD,mCAAuC;AACvC,iCAA4C;AAC5C,uCAA+C;AAExC,MAAM,YAAY,GAAG,CAAC,EAC3B,QAAQ,EACR,iBAAiB,EAIlB,EAAE,EAAE;IACH,OAAO,IAAA,oBAAE,EACP,oBAAY,EACZ,yBAAkB,EAClB,IAAA,oBAAY,EAAC,EAAE,QAAQ,EAAE,CAAC,EAC1B,+FAA+F,EAC/F,IAAA,4BAAkB,EAAC,iBAAiB,CAAC,EACrC,QAAQ,IAAI,0BAAe,CAC5B,CAAC;AACJ,CAAC,CAAC;AAfW,QAAA,YAAY,gBAevB;AAEK,MAAM,WAAW,GAAG,CAAC,EAC1B,QAAQ,EACR,OAAO,EACP,iBAAiB,EAKlB,EAAE,EAAE;IACH,OAAO,IAAA,oBAAE,EACP,yBAAkB,EAClB,+FAA+F,EAC/F,IAAA,4BAAkB,EAAC,iBAAiB,CAAC,EACrC,QAAQ,IAAI,0BAAe,EAC3B,OAAO,IAAI,mBAAW,CACvB,CAAC;AACJ,CAAC,CAAC;AAhBW,QAAA,WAAW,eAgBtB"}
@@ -0,0 +1,2 @@
1
+ export declare const defaultShimmer = "relative before:absolute before:inset-0 before:-translate-x-full before:animate-shimmer before:bg-gradient-to-r before:from-transparent before:via-neutral-100/20 before:to-transparent isolate overflow-hidden before:border-t before:border-neutral-100/20";
2
+ //# sourceMappingURL=shimmer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shimmer.d.ts","sourceRoot":"","sources":["../../../src/styles/shimmer.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,iQACqO,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2022 DXOS.org
4
+ //
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.defaultShimmer = void 0;
7
+ exports.defaultShimmer = 'relative before:absolute before:inset-0 before:-translate-x-full before:animate-shimmer before:bg-gradient-to-r before:from-transparent before:via-neutral-100/20 before:to-transparent isolate overflow-hidden before:border-t before:border-neutral-100/20';
8
+ //# sourceMappingURL=shimmer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shimmer.js","sourceRoot":"","sources":["../../../src/styles/shimmer.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,0BAA0B;AAC1B,EAAE;;;AAEW,QAAA,cAAc,GACzB,8PAA8P,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Vite plugin which configures a low-level design system for DXOS.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -31,12 +31,13 @@
31
31
  "jdenticon": "^3.2.0",
32
32
  "postcss": "^8.4.17",
33
33
  "qrcode.react": "^3.1.0",
34
+ "rci": "^0.0.3",
34
35
  "tailwindcss": "^3.1.8",
35
36
  "tailwindcss-logical": "^3.0.0",
36
37
  "tailwindcss-radix": "^2.6.0"
37
38
  },
38
39
  "devDependencies": {
39
- "@dxos/vite-plugin": "0.1.2",
40
+ "@dxos/vite-plugin": "0.1.4",
40
41
  "@types/react": "^18.0.21",
41
42
  "@types/react-dom": "^18.0.6",
42
43
  "@vitejs/plugin-react": "^2.0.1",
@@ -90,7 +90,7 @@ export const AlertDialog = ({
90
90
  {title}
91
91
  </AlertDialogPrimitive.Title>
92
92
  {description && (
93
- <AlertDialogPrimitive.Description className={cx('mt-2', defaultDescription)}>
93
+ <AlertDialogPrimitive.Description className={cx('my-2', defaultDescription)}>
94
94
  {description}
95
95
  </AlertDialogPrimitive.Description>
96
96
  )}
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import cx from 'classnames';
6
+ import { CodeInput, getSegmentCssWidth } from 'rci';
7
+ import React, { forwardRef, useCallback, ComponentProps } from 'react';
8
+
9
+ import { useForwardedRef, useIsFocused } from '../../hooks';
10
+ import { staticInput } from '../../styles/input';
11
+ import { InputProps } from './InputProps';
12
+
13
+ const bareInputStyleProps = {
14
+ padding: '8px',
15
+ spacing: '8px',
16
+ fontFamily: ''
17
+ };
18
+
19
+ export type BarePinInputProps = Omit<InputProps, 'ref' | 'label' | 'onChange'> &
20
+ Pick<ComponentProps<typeof CodeInput>, 'onChange' | 'value' | 'length'>;
21
+
22
+ // TODO(thure): supplying a `value` prop to CodeInput does not yield correct controlled input interactivity; this may be an issue with RCI (filed as https://github.com/leonardodino/rci/issues/25).
23
+ export const BarePinInput = forwardRef<HTMLInputElement, BarePinInputProps>(
24
+ ({ initialValue, size, validationMessage, validationValence, value, ...inputProps }, ref) => {
25
+ const width = getSegmentCssWidth('13px');
26
+ const inputRef = useForwardedRef(ref);
27
+ const inputFocused = useIsFocused(inputRef);
28
+
29
+ const renderSegment = useCallback<ComponentProps<typeof CodeInput>['renderSegment']>(
30
+ ({ state, index }) => (
31
+ <div
32
+ key={index}
33
+ className={staticInput({
34
+ focused: inputFocused && !!state,
35
+ disabled: inputProps.disabled,
36
+ ...(validationMessage && { validationValence })
37
+ })}
38
+ data-state={state}
39
+ style={{ width, height: '100%' }}
40
+ />
41
+ ),
42
+ [inputFocused, validationValence, validationMessage, inputProps.disabled]
43
+ );
44
+
45
+ return (
46
+ <CodeInput
47
+ {...{
48
+ spellCheck: false,
49
+ ...inputProps,
50
+ ...bareInputStyleProps,
51
+ inputRef,
52
+ className: cx(
53
+ 'font-mono selection:bg-transparent',
54
+ inputProps.disabled && 'cursor-not-allowed',
55
+ inputProps.className
56
+ ),
57
+ renderSegment
58
+ }}
59
+ />
60
+ );
61
+ }
62
+ );
@@ -0,0 +1,31 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import cx from 'classnames';
6
+ import React, { ComponentProps } from 'react';
7
+
8
+ import { defaultInput } from '../../styles/input';
9
+ import { InputProps, InputSize } from './InputProps';
10
+
11
+ const sizeMap: Record<InputSize, string> = {
12
+ md: 'text-sm',
13
+ lg: 'text-base',
14
+ pin: ''
15
+ };
16
+
17
+ export type BareTextInputProps = Omit<InputProps, 'label' | 'initialValue' | 'onChange'> &
18
+ Pick<ComponentProps<'input'>, 'onChange'>;
19
+
20
+ export const BareTextInput = ({ validationValence, validationMessage, size, ...inputProps }: BareTextInputProps) => {
21
+ return (
22
+ <input
23
+ {...inputProps}
24
+ className={cx(
25
+ defaultInput({ disabled: inputProps.disabled, ...(validationMessage && { validationValence }) }),
26
+ 'block w-full px-2.5 py-2',
27
+ sizeMap[size ?? 'md']
28
+ )}
29
+ />
30
+ );
31
+ };
@@ -16,6 +16,10 @@ export default {
16
16
  validationValence: {
17
17
  control: 'select',
18
18
  options: ['success', 'info', 'warning', 'error']
19
+ },
20
+ size: {
21
+ control: 'select',
22
+ options: ['md', 'lg', 'pin']
19
23
  }
20
24
  }
21
25
  };
@@ -33,7 +37,8 @@ Default.args = {
33
37
  labelVisuallyHidden: false,
34
38
  descriptionVisuallyHidden: false,
35
39
  validationMessage: '',
36
- validationValence: undefined
40
+ validationValence: undefined,
41
+ length: 6
37
42
  };
38
43
 
39
44
  export const Disabled = () => (
@@ -89,3 +94,15 @@ export const InputWithValidationAndDescription = () => (
89
94
  }}
90
95
  />
91
96
  );
97
+
98
+ export const PinInput = () => (
99
+ <Template
100
+ {...{
101
+ label: 'This input is a PIN-style input',
102
+ size: 'pin',
103
+ length: 6,
104
+ description: 'Type in secret you received',
105
+ placeholder: '••••••'
106
+ }}
107
+ />
108
+ );
@@ -3,39 +3,15 @@
3
3
  //
4
4
 
5
5
  import cx from 'classnames';
6
- import React, { ChangeEvent, ComponentProps, ReactNode, useCallback, useState, useTransition } from 'react';
6
+ import React, { ChangeEvent, useCallback, useState, useTransition } from 'react';
7
7
 
8
8
  import { useId } from '../../hooks';
9
- import { MessageValence } from '../../props';
10
- import {
11
- defaultDescription,
12
- defaultDisabled,
13
- defaultFocus,
14
- defaultHover,
15
- defaultPlaceholder,
16
- valenceColorText,
17
- valenceInputBorder
18
- } from '../../styles';
9
+ import { defaultDescription, valenceColorText } from '../../styles';
10
+ import { BarePinInput } from './BarePinInput';
11
+ import { BareTextInput } from './BareTextInput';
12
+ import { InputProps as NaturalInputProps } from './InputProps';
19
13
 
20
- export type InputSize = 'md' | 'lg';
21
-
22
- export interface InputProps extends Omit<ComponentProps<'input'>, 'value' | 'onChange' | 'size'> {
23
- label: ReactNode;
24
- labelVisuallyHidden?: boolean;
25
- description?: ReactNode;
26
- descriptionVisuallyHidden?: boolean;
27
- initialValue?: string;
28
- onChange?: (value: string) => void;
29
- disabled?: boolean;
30
- size?: InputSize;
31
- validationMessage?: ReactNode;
32
- validationValence?: MessageValence;
33
- }
34
-
35
- const sizeMap = new Map<InputSize, string>([
36
- ['md', ''],
37
- ['lg', 'text-base']
38
- ]);
14
+ export type InputProps = NaturalInputProps;
39
15
 
40
16
  export const Input = ({
41
17
  label,
@@ -49,6 +25,7 @@ export const Input = ({
49
25
  disabled,
50
26
  className,
51
27
  size,
28
+ length = 6,
52
29
  validationMessage,
53
30
  validationValence,
54
31
  ...inputProps
@@ -57,6 +34,8 @@ export const Input = ({
57
34
  const descriptionId = useId('input-description');
58
35
  const validationId = useId('input-validation');
59
36
 
37
+ const isInvalid = !!validationMessage && validationValence === 'error';
38
+
60
39
  const [_isPending, startTransition] = useTransition();
61
40
 
62
41
  const [internalValue, setInternalValue] = useState<string>(initialValue?.toString() || '');
@@ -73,7 +52,29 @@ export const Input = ({
73
52
  [onChange]
74
53
  );
75
54
 
76
- const isInvalid = !!validationMessage && validationValence === 'error';
55
+ const bareInputBaseProps = {
56
+ ...inputProps,
57
+ id: inputId,
58
+ ...(required && { required: true }),
59
+ ...(disabled && { disabled: true }),
60
+ ...(description && { 'aria-describedby': descriptionId }),
61
+ ...(isInvalid && {
62
+ 'aria-invalid': 'true' as const,
63
+ 'aria-errormessage': validationId
64
+ }),
65
+ ...(placeholder && { placeholder }),
66
+ value: internalValue,
67
+ onChange: onInternalChange,
68
+ validationMessage,
69
+ validationValence
70
+ };
71
+
72
+ const bareInput =
73
+ size === 'pin' ? (
74
+ <BarePinInput {...bareInputBaseProps} length={length} />
75
+ ) : (
76
+ <BareTextInput {...bareInputBaseProps} size={size} />
77
+ );
77
78
 
78
79
  return (
79
80
  <div className={cx('my-4', className)} role='none'>
@@ -86,29 +87,7 @@ export const Input = ({
86
87
  >
87
88
  {label}
88
89
  </label>
89
- <input
90
- id={inputId}
91
- {...inputProps}
92
- className={cx(
93
- defaultFocus,
94
- defaultPlaceholder,
95
- defaultHover({ disabled }),
96
- sizeMap.get(size ?? 'md'),
97
- 'bg-white/50 border text-neutral-900 text-sm rounded-lg block w-full px-2.5 py-2 dark:bg-neutral-700/50 dark:text-white',
98
- valenceInputBorder(validationMessage ? validationValence : undefined),
99
- disabled && defaultDisabled
100
- )}
101
- {...(required && { required: true })}
102
- {...(disabled && { disabled: true })}
103
- {...(placeholder && { placeholder })}
104
- {...(description && { 'aria-describedby': descriptionId })}
105
- {...(isInvalid && {
106
- 'aria-invalid': 'true',
107
- 'aria-errormessage': validationId
108
- })}
109
- value={internalValue}
110
- onChange={onInternalChange}
111
- />
90
+ {bareInput}
112
91
  {(description || validationMessage) && (
113
92
  <p
114
93
  {...(!isInvalid && { id: descriptionId })}
@@ -0,0 +1,23 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import { ComponentProps, ReactNode } from 'react';
6
+
7
+ import { MessageValence } from '../../props';
8
+
9
+ export type InputSize = 'md' | 'lg' | 'pin';
10
+
11
+ export interface InputProps extends Omit<ComponentProps<'input'>, 'value' | 'onChange' | 'size' | 'ref'> {
12
+ label: ReactNode;
13
+ labelVisuallyHidden?: boolean;
14
+ description?: ReactNode;
15
+ descriptionVisuallyHidden?: boolean;
16
+ initialValue?: string;
17
+ onChange?: (value: string) => void;
18
+ disabled?: boolean;
19
+ size?: InputSize;
20
+ validationMessage?: ReactNode;
21
+ validationValence?: MessageValence;
22
+ length?: number;
23
+ }
@@ -3,3 +3,5 @@
3
3
  //
4
4
 
5
5
  export * from './useId';
6
+ export * from './useForwardedRef';
7
+ export * from './useIsFocused';
@@ -0,0 +1,22 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import { useRef, useEffect } from 'react';
6
+
7
+ export const useForwardedRef = <T>(ref: React.ForwardedRef<T>) => {
8
+ const innerRef = useRef<T>(null);
9
+
10
+ useEffect(() => {
11
+ if (!ref) {
12
+ return;
13
+ }
14
+ if (typeof ref === 'function') {
15
+ ref(innerRef.current);
16
+ } else {
17
+ ref.current = innerRef.current;
18
+ }
19
+ });
20
+
21
+ return innerRef;
22
+ };
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ // Based upon the useIsFocused hook which is part of the `rci` project:
6
+ /// https://github.com/leonardodino/rci/blob/main/packages/use-is-focused
7
+
8
+ import { useEffect, useRef, useState, RefObject } from 'react';
9
+
10
+ export const useIsFocused = (inputRef: RefObject<HTMLInputElement>) => {
11
+ const [isFocused, setIsFocused] = useState<boolean | undefined>(undefined);
12
+ const isFocusedRef = useRef<boolean | undefined>(isFocused);
13
+
14
+ isFocusedRef.current = isFocused;
15
+
16
+ useEffect(() => {
17
+ const input = inputRef.current;
18
+ if (!input) {
19
+ return;
20
+ }
21
+
22
+ const onFocus = () => setIsFocused(true);
23
+ const onBlur = () => setIsFocused(false);
24
+ input.addEventListener('focus', onFocus);
25
+ input.addEventListener('blur', onBlur);
26
+
27
+ if (isFocusedRef.current === undefined) {
28
+ setIsFocused(document.activeElement === input);
29
+ }
30
+
31
+ return () => {
32
+ input.removeEventListener('focus', onFocus);
33
+ input.removeEventListener('blur', onBlur);
34
+ };
35
+ }, [inputRef, setIsFocused]);
36
+
37
+ return isFocused;
38
+ };
package/src/plugin.ts CHANGED
@@ -223,6 +223,12 @@ export const themePlugin = (options: VitePluginTailwindOptions) => {
223
223
  '100%': {
224
224
  transform: 'translateX(calc(100% + 1rem))'
225
225
  }
226
+ },
227
+ // Shimmer
228
+ 'shimmer-loop': {
229
+ '100%': {
230
+ transform: 'translateX(100%)'
231
+ }
226
232
  }
227
233
  },
228
234
  animation: {
@@ -248,7 +254,9 @@ export const themePlugin = (options: VitePluginTailwindOptions) => {
248
254
  'toast-hide': 'toast-hide 100ms ease-in forwards',
249
255
  'toast-slide-in-right': 'toast-slide-in-right 150ms cubic-bezier(0.16, 1, 0.3, 1)',
250
256
  'toast-slide-in-bottom': 'toast-slide-in-bottom 150ms cubic-bezier(0.16, 1, 0.3, 1)',
251
- 'toast-swipe-out': 'toast-swipe-out 100ms ease-out forwards'
257
+ 'toast-swipe-out': 'toast-swipe-out 100ms ease-out forwards',
258
+ // Shimmer
259
+ shimmer: 'shimmer-loop 2s infinite'
252
260
  }
253
261
  }
254
262
  },
@@ -4,3 +4,6 @@
4
4
 
5
5
  export const defaultFocus =
6
6
  'focus:outline-none focus-visible:hover:outline-none dark:focus-visible:hover:outline-none focus-visible:ring focus-visible:ring-offset-1 focus-visible:ring-primary-500 focus-visible:ring-offset-white dark:focus-visible:ring-primary-200 dark:focus-visible:ring-offset-black';
7
+
8
+ export const staticFocus =
9
+ 'ring ring-offset-1 ring-primary-500 ring-offset-white dark:ring-primary-200 dark:ring-offset-black';
@@ -8,6 +8,7 @@ export * from './focus';
8
8
  export * from './group';
9
9
  export * from './hover';
10
10
  export * from './ornament';
11
+ export * from './shimmer';
11
12
  export * from './size';
12
13
  export * from './text';
13
14
  export * from './valence';
@@ -0,0 +1,47 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import cx from 'classnames';
6
+
7
+ import { MessageValence } from '../props';
8
+ import { defaultDisabled } from './disabled';
9
+ import { defaultFocus, staticFocus } from './focus';
10
+ import { defaultHover } from './hover';
11
+ import { defaultPlaceholder } from './text';
12
+ import { valenceInputBorder } from './valence';
13
+
14
+ export const defaultInput = ({
15
+ disabled,
16
+ validationValence
17
+ }: {
18
+ disabled?: boolean;
19
+ validationValence?: MessageValence;
20
+ }) => {
21
+ return cx(
22
+ defaultFocus,
23
+ defaultPlaceholder,
24
+ defaultHover({ disabled }),
25
+ 'bg-white/50 border text-neutral-900 text-sm rounded-lg dark:bg-neutral-700/50 dark:text-white',
26
+ valenceInputBorder(validationValence),
27
+ disabled && defaultDisabled
28
+ );
29
+ };
30
+
31
+ export const staticInput = ({
32
+ disabled,
33
+ focused,
34
+ validationValence
35
+ }: {
36
+ disabled?: boolean;
37
+ focused?: boolean;
38
+ validationValence?: MessageValence;
39
+ }) => {
40
+ return cx(
41
+ defaultPlaceholder,
42
+ 'bg-white/50 border text-neutral-900 text-sm rounded-lg dark:bg-neutral-700/50 dark:text-white',
43
+ valenceInputBorder(validationValence),
44
+ disabled && defaultDisabled,
45
+ focused && staticFocus
46
+ );
47
+ };
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ export const defaultShimmer =
6
+ 'relative before:absolute before:inset-0 before:-translate-x-full before:animate-shimmer before:bg-gradient-to-r before:from-transparent before:via-neutral-100/20 before:to-transparent isolate overflow-hidden before:border-t before:border-neutral-100/20';