@react-spectrum/color 3.0.0-nightly.4564 → 3.0.0-nightly.4578

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 (96) hide show
  1. package/dist/ColorArea.main.js +11 -10
  2. package/dist/ColorArea.main.js.map +1 -1
  3. package/dist/ColorArea.mjs +12 -11
  4. package/dist/ColorArea.module.js +12 -11
  5. package/dist/ColorArea.module.js.map +1 -1
  6. package/dist/ColorEditor.32e497e8.css +20 -0
  7. package/dist/ColorEditor.32e497e8.css.map +1 -0
  8. package/dist/ColorEditor.main.js +116 -0
  9. package/dist/ColorEditor.main.js.map +1 -0
  10. package/dist/ColorEditor.mjs +111 -0
  11. package/dist/ColorEditor.module.js +111 -0
  12. package/dist/ColorEditor.module.js.map +1 -0
  13. package/dist/ColorField.main.js +44 -6
  14. package/dist/ColorField.main.js.map +1 -1
  15. package/dist/ColorField.mjs +46 -8
  16. package/dist/ColorField.module.js +46 -8
  17. package/dist/ColorField.module.js.map +1 -1
  18. package/dist/ColorPicker.ab9f47c0.css +204 -0
  19. package/dist/ColorPicker.ab9f47c0.css.map +1 -0
  20. package/dist/ColorPicker.main.js +125 -0
  21. package/dist/ColorPicker.main.js.map +1 -0
  22. package/dist/ColorPicker.mjs +116 -0
  23. package/dist/ColorPicker.module.js +116 -0
  24. package/dist/ColorPicker.module.js.map +1 -0
  25. package/dist/ColorSlider.main.js +8 -4
  26. package/dist/ColorSlider.main.js.map +1 -1
  27. package/dist/ColorSlider.mjs +9 -5
  28. package/dist/ColorSlider.module.js +9 -5
  29. package/dist/ColorSlider.module.js.map +1 -1
  30. package/dist/ColorSwatch.f6e6f811.css +260 -0
  31. package/dist/ColorSwatch.f6e6f811.css.map +1 -0
  32. package/dist/ColorSwatch.main.js +94 -0
  33. package/dist/ColorSwatch.main.js.map +1 -0
  34. package/dist/ColorSwatch.mjs +84 -0
  35. package/dist/ColorSwatch.module.js +84 -0
  36. package/dist/ColorSwatch.module.js.map +1 -0
  37. package/dist/ColorSwatchPicker.1575be06.css +356 -0
  38. package/dist/ColorSwatchPicker.1575be06.css.map +1 -0
  39. package/dist/ColorSwatchPicker.main.js +115 -0
  40. package/dist/ColorSwatchPicker.main.js.map +1 -0
  41. package/dist/ColorSwatchPicker.mjs +106 -0
  42. package/dist/ColorSwatchPicker.module.js +106 -0
  43. package/dist/ColorSwatchPicker.module.js.map +1 -0
  44. package/dist/ColorThumb.main.js +57 -7
  45. package/dist/ColorThumb.main.js.map +1 -1
  46. package/dist/ColorThumb.mjs +59 -9
  47. package/dist/ColorThumb.module.js +59 -9
  48. package/dist/ColorThumb.module.js.map +1 -1
  49. package/dist/ColorWheel.main.js +6 -2
  50. package/dist/ColorWheel.main.js.map +1 -1
  51. package/dist/ColorWheel.mjs +7 -3
  52. package/dist/ColorWheel.module.js +7 -3
  53. package/dist/ColorWheel.module.js.map +1 -1
  54. package/dist/colorarea_vars_css.main.js +0 -3
  55. package/dist/colorarea_vars_css.main.js.map +1 -1
  56. package/dist/colorarea_vars_css.mjs +0 -3
  57. package/dist/colorarea_vars_css.module.js +0 -3
  58. package/dist/colorarea_vars_css.module.js.map +1 -1
  59. package/dist/en-US.main.js +10 -0
  60. package/dist/en-US.main.js.map +1 -0
  61. package/dist/en-US.mjs +12 -0
  62. package/dist/en-US.module.js +12 -0
  63. package/dist/en-US.module.js.map +1 -0
  64. package/dist/import.mjs +11 -1
  65. package/dist/intlStrings.main.js +9 -0
  66. package/dist/intlStrings.main.js.map +1 -0
  67. package/dist/intlStrings.mjs +11 -0
  68. package/dist/intlStrings.module.js +11 -0
  69. package/dist/intlStrings.module.js.map +1 -0
  70. package/dist/main.js +16 -0
  71. package/dist/main.js.map +1 -1
  72. package/dist/module.js +11 -1
  73. package/dist/module.js.map +1 -1
  74. package/dist/types.d.ts +75 -4
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/{vars.08ba4b4c.css → vars.53b417c1.css} +2 -3
  77. package/dist/vars.53b417c1.css.map +1 -0
  78. package/dist/{vars.6f3d3943.css → vars.6fa9fa04.css} +6 -18
  79. package/dist/vars.6fa9fa04.css.map +1 -0
  80. package/dist/{vars.571f903e.css → vars.aa07b6d2.css} +2 -2
  81. package/dist/{vars.571f903e.css.map → vars.aa07b6d2.css.map} +1 -1
  82. package/dist/{vars.ef2c01b8.css → vars.cc682729.css} +4 -4
  83. package/dist/{vars.ef2c01b8.css.map → vars.cc682729.css.map} +1 -1
  84. package/package.json +23 -17
  85. package/src/ColorArea.tsx +7 -6
  86. package/src/ColorEditor.tsx +63 -0
  87. package/src/ColorField.tsx +67 -14
  88. package/src/ColorPicker.tsx +122 -0
  89. package/src/ColorSlider.tsx +6 -4
  90. package/src/ColorSwatch.tsx +102 -0
  91. package/src/ColorSwatchPicker.tsx +118 -0
  92. package/src/ColorThumb.tsx +72 -25
  93. package/src/ColorWheel.tsx +5 -2
  94. package/src/index.ts +10 -0
  95. package/dist/vars.08ba4b4c.css.map +0 -1
  96. package/dist/vars.6f3d3943.css.map +0 -1
@@ -4,8 +4,8 @@
4
4
  transform: translate(0, var(--spectrum-global-dimension-static-size-100, 8px));
5
5
  opacity: 0;
6
6
  transform-origin: bottom;
7
- bottom: calc(50% + var(--spectrum-global-dimension-static-size-200, 16px));
8
- left: calc(50% - calc(calc(var(--spectrum-colorloupe-width, var(--spectrum-global-dimension-static-size-600)) + var(--spectrum-colorhandle-inner-border-size, var(--spectrum-global-dimension-static-size-25)) * 2) / 2));
7
+ margin-top: calc(calc(var(--spectrum-colorloupe-height, var(--spectrum-global-dimension-static-size-800)) + var(--spectrum-colorhandle-inner-border-size, var(--spectrum-global-dimension-static-size-25)) * 2) * -1 - var(--spectrum-global-dimension-static-size-200, 16px));
8
+ margin-left: calc(calc(calc(var(--spectrum-colorloupe-width, var(--spectrum-global-dimension-static-size-600)) + var(--spectrum-colorhandle-inner-border-size, var(--spectrum-global-dimension-static-size-25)) * 2) / -2));
9
9
  pointer-events: none;
10
10
  transition: transform .1s ease-in-out, opacity .125s ease-in-out;
11
11
  position: absolute;
@@ -28,7 +28,7 @@
28
28
  }
29
29
 
30
30
  .HpWpfq_spectrum-ColorLoupe-inner-checker {
31
- fill: var(--spectrum-global-color-static-gray-500, #bcbcbc);
31
+ fill: #e6e6e6;
32
32
  }
33
33
 
34
34
  @media (forced-colors: active) {
@@ -38,4 +38,4 @@
38
38
  --spectrum-colorloupe-outer-border-color: ButtonFace;
39
39
  }
40
40
  }
41
- /*# sourceMappingURL=vars.ef2c01b8.css.map */
41
+ /*# sourceMappingURL=vars.cc682729.css.map */
@@ -1 +1 @@
1
- {"mappings":"AAYA;;;;;;;;;;;;;AAuBE;;;;;;AAOF;;;;;;AASA;;;;AAIA;;;;AAIA;EACE","sources":["packages/@adobe/spectrum-css-temp/components/colorloupe/vars.css"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n@import './index.css';\n@import './skin.css';\n"],"names":[],"version":3,"file":"vars.ef2c01b8.css.map"}
1
+ {"mappings":"AAYA;;;;;;;;;;;;;AA0BE;;;;;;AAOF;;;;;;AASA;;;;AAIA;;;;AAIA;EACE","sources":["packages/@adobe/spectrum-css-temp/components/colorloupe/vars.css"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n@import './index.css';\n@import './skin.css';\n"],"names":[],"version":3,"file":"vars.cc682729.css.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-spectrum/color",
3
- "version": "3.0.0-nightly.4564+315950cef",
3
+ "version": "3.0.0-nightly.4578+b09a14eb1",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -36,23 +36,29 @@
36
36
  "url": "https://github.com/adobe/react-spectrum"
37
37
  },
38
38
  "dependencies": {
39
- "@react-aria/color": "3.0.0-nightly.4564+315950cef",
40
- "@react-aria/focus": "3.0.0-nightly.2852+315950cef",
41
- "@react-aria/i18n": "3.0.0-nightly.2852+315950cef",
42
- "@react-aria/interactions": "3.0.0-nightly.2852+315950cef",
43
- "@react-aria/utils": "3.0.0-nightly.2852+315950cef",
44
- "@react-spectrum/form": "3.0.0-nightly.2852+315950cef",
45
- "@react-spectrum/label": "3.16.5-nightly.4564+315950cef",
46
- "@react-spectrum/textfield": "3.0.0-nightly.2852+315950cef",
47
- "@react-spectrum/utils": "3.0.0-nightly.2852+315950cef",
48
- "@react-stately/color": "3.5.4-nightly.4564+315950cef",
49
- "@react-types/color": "3.0.0-nightly.4564+315950cef",
50
- "@react-types/shared": "3.0.0-nightly.2852+315950cef",
51
- "@react-types/textfield": "3.0.0-nightly.2852+315950cef",
52
- "@swc/helpers": "^0.5.0"
39
+ "@react-aria/color": "3.0.0-nightly.4578+b09a14eb1",
40
+ "@react-aria/focus": "3.0.0-nightly.2866+b09a14eb1",
41
+ "@react-aria/i18n": "3.0.0-nightly.2866+b09a14eb1",
42
+ "@react-aria/interactions": "3.0.0-nightly.2866+b09a14eb1",
43
+ "@react-aria/utils": "3.0.0-nightly.2866+b09a14eb1",
44
+ "@react-spectrum/dialog": "3.0.0-nightly.2866+b09a14eb1",
45
+ "@react-spectrum/form": "3.0.0-nightly.2866+b09a14eb1",
46
+ "@react-spectrum/label": "3.16.5-nightly.4578+b09a14eb1",
47
+ "@react-spectrum/overlays": "3.0.0-nightly.2866+b09a14eb1",
48
+ "@react-spectrum/picker": "3.14.4-nightly.4578+b09a14eb1",
49
+ "@react-spectrum/textfield": "3.0.0-nightly.2866+b09a14eb1",
50
+ "@react-spectrum/utils": "3.0.0-nightly.2866+b09a14eb1",
51
+ "@react-spectrum/view": "3.0.0-nightly.2866+b09a14eb1",
52
+ "@react-stately/color": "3.5.4-nightly.4578+b09a14eb1",
53
+ "@react-types/color": "3.0.0-nightly.4578+b09a14eb1",
54
+ "@react-types/shared": "3.0.0-nightly.2866+b09a14eb1",
55
+ "@react-types/textfield": "3.0.0-nightly.2866+b09a14eb1",
56
+ "@swc/helpers": "^0.5.0",
57
+ "react-aria-components": "1.1.2-nightly.4578+b09a14eb1"
53
58
  },
54
59
  "devDependencies": {
55
- "@adobe/spectrum-css-temp": "3.0.0-nightly.2852+315950cef"
60
+ "@adobe/spectrum-css-temp": "3.0.0-nightly.2866+b09a14eb1",
61
+ "@react-spectrum/style-macro-s1": "1.0.0-nightly.4578+b09a14eb1"
56
62
  },
57
63
  "peerDependencies": {
58
64
  "@react-spectrum/provider": "^3.0.0",
@@ -62,5 +68,5 @@
62
68
  "publishConfig": {
63
69
  "access": "public"
64
70
  },
65
- "gitHead": "315950cef7952de30220661f62ab79ba6dcb59cc"
71
+ "gitHead": "b09a14eb1854d9d52e08739e30aa8fae51f1595a"
66
72
  }
package/src/ColorArea.tsx CHANGED
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import {classNames, dimensionValue, useFocusableRef, useStyleProps} from '@react-spectrum/utils';
14
+ import {ColorAreaContext, useContextProps} from 'react-aria-components';
14
15
  import {ColorThumb} from './ColorThumb';
15
16
  import {FocusableRef} from '@react-types/shared';
16
17
  import {mergeProps} from '@react-aria/utils';
@@ -24,20 +25,20 @@ import {useProviderProps} from '@react-spectrum/provider';
24
25
 
25
26
  function ColorArea(props: SpectrumColorAreaProps, ref: FocusableRef<HTMLDivElement>) {
26
27
  props = useProviderProps(props);
28
+ let inputXRef = useRef(null);
29
+ let inputYRef = useRef(null);
30
+ let containerRef = useFocusableRef(ref, inputXRef);
31
+ [props, containerRef] = useContextProps(props, containerRef, ColorAreaContext);
27
32
 
28
33
  let {isDisabled} = props;
29
34
  let size = props.size && dimensionValue(props.size);
30
35
  let {styleProps} = useStyleProps(props);
31
36
 
32
- let inputXRef = useRef(null);
33
- let inputYRef = useRef(null);
34
- let containerRef = useFocusableRef(ref, inputXRef);
35
37
 
36
38
  let state = useColorAreaState(props);
37
39
 
38
40
  let {
39
41
  colorAreaProps,
40
- gradientProps,
41
42
  xInputProps,
42
43
  yInputProps,
43
44
  thumbProps
@@ -59,18 +60,18 @@ function ColorArea(props: SpectrumColorAreaProps, ref: FocusableRef<HTMLDivEleme
59
60
  }
60
61
  ref={containerRef}
61
62
  style={{
62
- ...colorAreaProps.style,
63
+ ...(isDisabled ? {} : colorAreaProps.style),
63
64
  ...styleProps.style,
64
65
  // Workaround around https://github.com/adobe/spectrum-css/issues/1032
65
66
  width: size,
66
67
  height: size
67
68
  }}>
68
- <div {...gradientProps} className={classNames(styles, 'spectrum-ColorArea-gradient')} />
69
69
  <ColorThumb
70
70
  value={state.getDisplayColor()}
71
71
  isFocused={isFocusVisible}
72
72
  isDisabled={isDisabled}
73
73
  isDragging={state.isDragging}
74
+ containerRef={containerRef}
74
75
  className={classNames(styles, 'spectrum-ColorArea-handle')}
75
76
  {...thumbProps}>
76
77
  <div role="presentation">
@@ -0,0 +1,63 @@
1
+ import {ColorArea} from './ColorArea';
2
+ import {ColorField} from './ColorField';
3
+ import {ColorSlider} from './ColorSlider';
4
+ import {ColorSpace} from '@react-types/color';
5
+ import {DOMRef} from '@react-types/shared';
6
+ import {getColorChannels} from '@react-stately/color';
7
+ // @ts-ignore
8
+ import intlMessages from '../intl/*.json';
9
+ import {Item, Picker} from '@react-spectrum/picker';
10
+ import React, {CSSProperties, useState} from 'react';
11
+ import {style} from '@react-spectrum/style-macro-s1' with {type: 'macro'};
12
+ import {useDOMRef} from '@react-spectrum/utils';
13
+ import {useLocalizedStringFormatter} from '@react-aria/i18n';
14
+
15
+ export interface SpectrumColorEditorProps {
16
+ /** Whether to hide the alpha channel color slider and color field. */
17
+ hideAlphaChannel?: boolean
18
+ }
19
+
20
+ function ColorEditor(props: SpectrumColorEditorProps, ref: DOMRef<HTMLDivElement>) {
21
+ let [format, setFormat] = useState<ColorSpace | 'hex'>('hex');
22
+ let domRef = useDOMRef(ref);
23
+ let formatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/color');
24
+
25
+ return (
26
+ <div className={style({display: 'flex', flexDirection: 'column', gap: 4})()} ref={domRef}>
27
+ <div className={style({display: 'flex', gap: 4})()}>
28
+ <ColorArea colorSpace="hsb" xChannel="saturation" yChannel="brightness" />
29
+ <ColorSlider colorSpace="hsb" channel="hue" orientation="vertical" />
30
+ {!props.hideAlphaChannel &&
31
+ <ColorSlider channel="alpha" orientation="vertical" />
32
+ }
33
+ </div>
34
+ <div className={style({display: 'flex', gap: 4})()}>
35
+ <Picker
36
+ aria-label={formatter.format('colorFormat')}
37
+ isQuiet
38
+ width="size-700"
39
+ menuWidth="size-1000"
40
+ selectedKey={format}
41
+ onSelectionChange={f => setFormat(f as typeof format)}>
42
+ <Item key="hex">{formatter.format('hex')}</Item>
43
+ <Item key="rgb">{formatter.format('rgb')}</Item>
44
+ <Item key="hsl">{formatter.format('hsl')}</Item>
45
+ <Item key="hsb">{formatter.format('hsb')}</Item>
46
+ </Picker>
47
+ {format === 'hex'
48
+ ? <ColorField isQuiet width="size-1000" aria-label={formatter.format('hex')} />
49
+ : getColorChannels(format).map(channel => (
50
+ <ColorField key={channel} colorSpace={format === 'hex' ? 'rgb' : format} channel={channel} isQuiet width="size-400" flex UNSAFE_style={{'--spectrum-textfield-min-width': 0} as CSSProperties} />
51
+ ))}
52
+ {!props.hideAlphaChannel &&
53
+ <ColorField channel="alpha" isQuiet width="size-400" flex UNSAFE_style={{'--spectrum-textfield-min-width': 0} as CSSProperties} />}
54
+ </div>
55
+ </div>
56
+ );
57
+ }
58
+
59
+ /**
60
+ * ColorEditor provides a default UI for editing colors within a ColorPicker.
61
+ */
62
+ let _ColorEditor = React.forwardRef(ColorEditor);
63
+ export {_ColorEditor as ColorEditor};
@@ -11,46 +11,99 @@
11
11
  */
12
12
 
13
13
  import {classNames} from '@react-spectrum/utils';
14
+ import {ColorChannel, SpectrumColorFieldProps} from '@react-types/color';
15
+ import {ColorFieldContext, useContextProps} from 'react-aria-components';
14
16
  import React, {Ref, useRef} from 'react';
15
- import {SpectrumColorFieldProps} from '@react-types/color';
16
17
  import styles from './colorfield.css';
17
18
  import {TextFieldBase} from '@react-spectrum/textfield';
18
19
  import {TextFieldRef} from '@react-types/textfield';
19
- import {useColorField} from '@react-aria/color';
20
- import {useColorFieldState} from '@react-stately/color';
20
+ import {useColorChannelField, useColorField} from '@react-aria/color';
21
+ import {useColorChannelFieldState, useColorFieldState} from '@react-stately/color';
21
22
  import {useFormProps} from '@react-spectrum/form';
23
+ import {useLocale} from '@react-aria/i18n';
22
24
  import {useProviderProps} from '@react-spectrum/provider';
23
25
 
24
26
  function ColorField(props: SpectrumColorFieldProps, ref: Ref<TextFieldRef>) {
25
27
  props = useProviderProps(props);
26
28
  props = useFormProps(props);
29
+ [props] = useContextProps(props, null, ColorFieldContext);
30
+ if (props.placeholder) {
31
+ console.warn('Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/ColorField.html#help-text');
32
+ }
33
+
34
+ if (props.channel) {
35
+ return <ColorChannelField {...props} channel={props.channel} forwardedRef={ref} />;
36
+ } else {
37
+ return <HexColorField {...props} forwardedRef={ref} />;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * A color field allows users to edit a hex color or individual color channel value.
43
+ */
44
+ const _ColorField = React.forwardRef(ColorField);
45
+ export {_ColorField as ColorField};
46
+
47
+ interface ColorChannelFieldProps extends Omit<SpectrumColorFieldProps, 'channel'> {
48
+ channel: ColorChannel,
49
+ forwardedRef: Ref<TextFieldRef>
50
+ }
51
+
52
+ function ColorChannelField(props: ColorChannelFieldProps) {
27
53
  let {
28
54
  // These disabled props are handled by the state hook
29
55
  value, // eslint-disable-line @typescript-eslint/no-unused-vars
30
56
  defaultValue, // eslint-disable-line @typescript-eslint/no-unused-vars
31
57
  onChange, // eslint-disable-line @typescript-eslint/no-unused-vars
58
+ validate, // eslint-disable-line @typescript-eslint/no-unused-vars
59
+ forwardedRef,
60
+ ...otherProps
61
+ } = props;
62
+ let {locale} = useLocale();
63
+ let state = useColorChannelFieldState({
64
+ ...props,
65
+ locale
66
+ });
67
+
68
+ let inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null);
69
+ let result = useColorChannelField(otherProps, state, inputRef);
70
+
71
+ return (
72
+ <>
73
+ <TextFieldBase
74
+ {...otherProps}
75
+ ref={forwardedRef}
76
+ inputRef={inputRef}
77
+ {...result}
78
+ inputClassName={classNames(styles, 'react-spectrum-ColorField-input')} />
79
+ {props.name && <input type="hidden" name={props.name} value={isNaN(state.numberValue) ? '' : state.numberValue} />}
80
+ </>
81
+ );
82
+ }
83
+
84
+ interface HexColorFieldProps extends SpectrumColorFieldProps {
85
+ forwardedRef: Ref<TextFieldRef>
86
+ }
87
+
88
+ function HexColorField(props: HexColorFieldProps) {
89
+ let {
90
+ // These disabled props are handled by the state hook
91
+ value, // eslint-disable-line @typescript-eslint/no-unused-vars
92
+ defaultValue, // eslint-disable-line @typescript-eslint/no-unused-vars
93
+ onChange, // eslint-disable-line @typescript-eslint/no-unused-vars
94
+ forwardedRef,
32
95
  ...otherProps
33
96
  } = props;
34
97
  let state = useColorFieldState(props);
35
98
  let inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null);
36
99
  let result = useColorField(otherProps, state, inputRef);
37
100
 
38
- if (props.placeholder) {
39
- console.warn('Placeholders are deprecated due to accessibility issues. Please use help text instead. See the docs for details: https://react-spectrum.adobe.com/react-spectrum/ColorField.html#help-text');
40
- }
41
-
42
101
  return (
43
102
  <TextFieldBase
44
103
  {...otherProps}
45
- ref={ref}
104
+ ref={forwardedRef}
46
105
  inputRef={inputRef}
47
106
  {...result}
48
107
  inputClassName={classNames(styles, 'react-spectrum-ColorField-input')} />
49
108
  );
50
109
  }
51
-
52
- /**
53
- * ColorFields allow users to enter a color in #rrggbb hexadecimal format.
54
- */
55
- const _ColorField = React.forwardRef(ColorField);
56
- export {_ColorField as ColorField};
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {ColorPicker as AriaColorPicker, Button, Color} from 'react-aria-components';
14
+ import {AriaLabelingProps, FocusableRef, ValueBase} from '@react-types/shared';
15
+ import {ColorSwatch} from './ColorSwatch';
16
+ import {Content} from '@react-spectrum/view';
17
+ import {Dialog, DialogTrigger} from '@react-spectrum/dialog';
18
+ import React, {ReactNode, useRef} from 'react';
19
+ import {style} from '@react-spectrum/style-macro-s1' with {type: 'macro'};
20
+ import {unwrapDOMRef, useFocusableRef} from '@react-spectrum/utils';
21
+ import {useId} from '@react-aria/utils';
22
+
23
+ export interface SpectrumColorPickerProps extends ValueBase<string | Color, Color>, AriaLabelingProps {
24
+ /** A visual label for the color picker. */
25
+ label?: ReactNode,
26
+ /** The contents of the color picker popover, e.g. `<ColorEditor />`. */
27
+ children?: ReactNode,
28
+ /**
29
+ * The size of the color swatch.
30
+ * @default "M"
31
+ */
32
+ size?: 'XS' | 'S' | 'M' | 'L',
33
+ /**
34
+ * The corner rounding of the color swatch.
35
+ * @default "default"
36
+ */
37
+ rounding?: 'default' | 'none' | 'full'
38
+ }
39
+
40
+ function ColorPicker(props: SpectrumColorPickerProps, ref: FocusableRef<HTMLButtonElement>) {
41
+ let swatchRef = useRef(null);
42
+ let domRef = useFocusableRef(ref);
43
+ let labelId = useId();
44
+ return (
45
+ <AriaColorPicker {...props}>
46
+ <DialogTrigger type="popover" mobileType="tray" targetRef={unwrapDOMRef(swatchRef)}>
47
+ <Button
48
+ ref={domRef}
49
+ className={style({
50
+ backgroundColor: 'transparent',
51
+ borderStyle: 'none',
52
+ padding: 0,
53
+ display: 'flex',
54
+ alignItems: 'center',
55
+ gap: 'text-to-control',
56
+ outlineStyle: 'none',
57
+ fontFamily: 'sans',
58
+ color: 'body',
59
+ fontSize: {
60
+ size: {
61
+ XS: 'xs',
62
+ S: 'sm',
63
+ M: 'base',
64
+ L: 'lg'
65
+ }
66
+ }
67
+ })({size: props.size || 'M'})}>
68
+ {({isFocusVisible}) => (
69
+ <>
70
+ <div
71
+ className={style({
72
+ outlineStyle: {
73
+ default: 'none',
74
+ isFocusVisible: 'solid'
75
+ },
76
+ outlineColor: 'focus-ring',
77
+ outlineWidth: 2,
78
+ outlineOffset: 2,
79
+ borderRadius: 'default'
80
+ })({isFocusVisible})}>
81
+ <ColorSwatch
82
+ ref={swatchRef}
83
+ size={props.size}
84
+ rounding={props.rounding}
85
+ aria-label={props['aria-label']}
86
+ aria-labelledby={props['aria-labelledby']}
87
+ aria-describedby={props['aria-describedby']}
88
+ aria-details={props['aria-details']} />
89
+ </div>
90
+ {props.label &&
91
+ <span id={labelId}>{props.label}</span>
92
+ }
93
+ </>
94
+ )}
95
+ </Button>
96
+ <Dialog
97
+ aria-labelledby={props.label ? labelId : props['aria-labelledby']}
98
+ aria-label={props['aria-label']}
99
+ UNSAFE_style={{
100
+ width: 'fit-content',
101
+ minWidth: 0,
102
+ margin: '0 auto' // Center within tray.
103
+ }}>
104
+ <Content
105
+ UNSAFE_style={{
106
+ position: 'relative',
107
+ margin: 'calc(var(--spectrum-dialog-padding) * -1)',
108
+ padding: 'var(--spectrum-global-dimension-size-200)'
109
+ }}>
110
+ {props.children}
111
+ </Content>
112
+ </Dialog>
113
+ </DialogTrigger>
114
+ </AriaColorPicker>
115
+ );
116
+ }
117
+
118
+ /**
119
+ * A ColorPicker combines a swatch with a customizable popover for editing a color.
120
+ */
121
+ let _ColorPicker = React.forwardRef(ColorPicker);
122
+ export {_ColorPicker as ColorPicker};
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import {classNames, SlotProvider, useFocusableRef, useStyleProps} from '@react-spectrum/utils';
14
+ import {ColorSliderContext, useContextProps} from 'react-aria-components';
14
15
  import {ColorThumb} from './ColorThumb';
15
16
  import {FocusableRef} from '@react-types/shared';
16
17
  import {Label} from '@react-spectrum/label';
@@ -25,6 +26,10 @@ import {useProviderProps} from '@react-spectrum/provider';
25
26
 
26
27
  function ColorSlider(props: SpectrumColorSliderProps, ref: FocusableRef<HTMLDivElement>) {
27
28
  props = useProviderProps(props);
29
+ let inputRef = useRef(null);
30
+ let trackRef = useRef(null);
31
+ let domRef = useFocusableRef(ref, inputRef);
32
+ [props, domRef] = useContextProps(props, domRef, ColorSliderContext);
28
33
 
29
34
  let {
30
35
  isDisabled,
@@ -39,10 +44,6 @@ function ColorSlider(props: SpectrumColorSliderProps, ref: FocusableRef<HTMLDivE
39
44
  let {styleProps} = useStyleProps(props);
40
45
  let {locale} = useLocale();
41
46
 
42
- let inputRef = useRef(null);
43
- let trackRef = useRef(null);
44
- let domRef = useFocusableRef(ref, inputRef);
45
-
46
47
  let state = useColorSliderState({...props, locale});
47
48
 
48
49
  // If vertical and a label is provided, use it as an aria-label instead.
@@ -126,6 +127,7 @@ function ColorSlider(props: SpectrumColorSliderProps, ref: FocusableRef<HTMLDivE
126
127
  isFocused={isFocused && isFocusVisible}
127
128
  isDisabled={isDisabled}
128
129
  isDragging={state.isThumbDragging(0)}
130
+ containerRef={trackRef}
129
131
  className={classNames(styles, 'spectrum-ColorSlider-handle')}
130
132
  {...thumbProps}>
131
133
  <input {...inputProps} {...focusProps} ref={inputRef} className={classNames(styles, 'spectrum-ColorSlider-slider')} />
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {AriaColorSwatchProps, useColorSwatch} from '@react-aria/color';
14
+ import {Color} from '@react-types/color';
15
+ import {ColorSwatchContext, useContextProps} from 'react-aria-components';
16
+ import {DOMRef, StyleProps} from '@react-types/shared';
17
+ import React, {createContext, forwardRef, JSX, ReactElement, useContext} from 'react';
18
+ import {style} from '@react-spectrum/style-macro-s1' with {type: 'macro'};
19
+ import {useDOMRef, useStyleProps} from '@react-spectrum/utils';
20
+
21
+ export interface SpectrumColorSwatchProps extends AriaColorSwatchProps, StyleProps {
22
+ /**
23
+ * The size of the ColorSwatch.
24
+ * @default "M"
25
+ */
26
+ size?: 'XS' | 'S' | 'M' | 'L',
27
+ /**
28
+ * The corner rounding of the ColorSwatch.
29
+ * @default "default"
30
+ */
31
+ rounding?: 'default' | 'none' | 'full'
32
+ }
33
+
34
+ interface SpectrumColorSwatchContextValue extends Pick<SpectrumColorSwatchProps, 'size' | 'rounding'> {
35
+ useWrapper: (swatch: ReactElement, color: Color, rounding: SpectrumColorSwatchProps['rounding']) => JSX.Element
36
+ }
37
+
38
+ export const SpectrumColorSwatchContext = createContext<SpectrumColorSwatchContextValue | null>(null);
39
+
40
+ function ColorSwatch(props: SpectrumColorSwatchProps, ref: DOMRef<HTMLDivElement>): JSX.Element {
41
+ let domRef = useDOMRef(ref);
42
+ [props, domRef] = useContextProps(props, domRef, ColorSwatchContext);
43
+ let {colorSwatchProps, color} = useColorSwatch(props);
44
+ let {styleProps} = useStyleProps(props);
45
+ let ctx = useContext(SpectrumColorSwatchContext);
46
+ let {
47
+ size = ctx?.size || 'M',
48
+ rounding = ctx?.rounding || 'default'
49
+ } = props;
50
+
51
+ let swatch = (
52
+ <div
53
+ {...colorSwatchProps}
54
+ {...styleProps}
55
+ ref={domRef}
56
+ style={{
57
+ ...styleProps.style,
58
+ // TODO: should there be a distinction between transparent and no value (e.g. null)?
59
+ background: color.getChannelValue('alpha') > 0
60
+ ? `linear-gradient(${color}, ${color}), repeating-conic-gradient(#e6e6e6 0% 25%, white 0% 50%) 0% 50% / 16px 16px`
61
+ // Red slash to indicate there is no selected color.
62
+ : 'linear-gradient(to bottom right, transparent calc(50% - 2px), var(--spectrum-red-900) calc(50% - 2px) calc(50% + 2px), transparent calc(50% + 2px)) no-repeat'
63
+ }}
64
+ className={style({
65
+ size: {
66
+ size: {
67
+ XS: 4,
68
+ S: 6,
69
+ M: 8,
70
+ L: 10
71
+ }
72
+ },
73
+ borderRadius: {
74
+ rounding: {
75
+ default: 'default',
76
+ none: 'none',
77
+ full: 'full'
78
+ }
79
+ },
80
+ // Trick to create a partially transparent color from a variable.
81
+ // Ideally we'd use relative color syntax for this but it's not in Firefox yet.
82
+ borderColor: '[color-mix(in srgb, var(--spectrum-gray-900), transparent 49%)]',
83
+ borderWidth: 1,
84
+ borderStyle: 'solid',
85
+ boxSizing: 'border-box',
86
+ forcedColorAdjust: 'none'
87
+ })({size, rounding})} />
88
+ );
89
+
90
+ // ColorSwatchPicker needs to wrap the swatch in a ListBoxItem.
91
+ if (ctx) {
92
+ return ctx.useWrapper(swatch, color, rounding);
93
+ }
94
+
95
+ return swatch;
96
+ }
97
+
98
+ /**
99
+ * A ColorSwatch displays a preview of a selected color.
100
+ */
101
+ let _ColorSwatch = forwardRef(ColorSwatch);
102
+ export {_ColorSwatch as ColorSwatch};