reshaped 3.7.4 → 3.8.0-canary.1

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 (110) hide show
  1. package/CHANGELOG-extra.md +3 -0
  2. package/CHANGELOG.md +68 -55
  3. package/LICENSE.md +1 -1
  4. package/README.md +24 -0
  5. package/dist/bundle.css +1 -1
  6. package/dist/bundle.js +11 -11
  7. package/dist/cjs/themes/index.d.ts +1 -0
  8. package/dist/cjs/themes/index.js +3 -1
  9. package/dist/components/Accordion/Accordion.types.d.ts +13 -2
  10. package/dist/components/ActionBar/ActionBar.types.d.ts +10 -0
  11. package/dist/components/Actionable/Actionable.types.d.ts +14 -0
  12. package/dist/components/Alert/Alert.types.d.ts +11 -0
  13. package/dist/components/Autocomplete/Autocomplete.types.d.ts +7 -0
  14. package/dist/components/Avatar/Avatar.types.d.ts +18 -0
  15. package/dist/components/Avatar/tests/Avatar.stories.js +1 -1
  16. package/dist/components/Badge/Badge.types.d.ts +25 -1
  17. package/dist/components/Badge/tests/Badge.test.stories.js +3 -1
  18. package/dist/components/Breadcrumbs/Breadcrumbs.types.d.ts +11 -0
  19. package/dist/components/Button/Button.types.d.ts +20 -0
  20. package/dist/components/Calendar/Calendar.types.d.ts +31 -0
  21. package/dist/components/Calendar/tests/Calendar.stories.js +1 -1
  22. package/dist/components/Card/Card.types.d.ts +12 -0
  23. package/dist/components/Carousel/Carousel.types.d.ts +13 -0
  24. package/dist/components/Checkbox/Checkbox.types.d.ts +19 -0
  25. package/dist/components/Checkbox/tests/Checkbox.stories.js +1 -1
  26. package/dist/components/CheckboxGroup/CheckboxGroup.types.d.ts +10 -0
  27. package/dist/components/Container/Container.types.d.ts +11 -1
  28. package/dist/components/Dismissible/Dismissible.types.d.ts +10 -0
  29. package/dist/components/Divider/Divider.types.d.ts +6 -0
  30. package/dist/components/DropdownMenu/DropdownMenu.types.d.ts +4 -1
  31. package/dist/components/FileUpload/FileUpload.types.d.ts +10 -0
  32. package/dist/components/Flyout/Flyout.types.d.ts +41 -0
  33. package/dist/components/Flyout/FlyoutContent.js +1 -1
  34. package/dist/components/Flyout/FlyoutControlled.js +2 -1
  35. package/dist/components/Flyout/tests/Flyout.stories.d.ts +4 -0
  36. package/dist/components/Flyout/tests/Flyout.stories.js +59 -1
  37. package/dist/components/Flyout/useFlyout.d.ts +1 -0
  38. package/dist/components/Flyout/useFlyout.js +3 -1
  39. package/dist/components/Flyout/utilities/calculatePosition.d.ts +1 -1
  40. package/dist/components/Flyout/utilities/calculatePosition.js +52 -28
  41. package/dist/components/Flyout/utilities/flyout.js +22 -18
  42. package/dist/components/Flyout/utilities/helpers.d.ts +7 -0
  43. package/dist/components/Flyout/utilities/helpers.js +14 -0
  44. package/dist/components/Flyout/utilities/isFullyVisible.d.ts +5 -1
  45. package/dist/components/Flyout/utilities/isFullyVisible.js +1 -1
  46. package/dist/components/FormControl/FormControl.types.d.ts +9 -0
  47. package/dist/components/Grid/Grid.js +3 -1
  48. package/dist/components/Grid/Grid.module.css +1 -1
  49. package/dist/components/Grid/Grid.types.d.ts +31 -0
  50. package/dist/components/Grid/tests/Grid.stories.d.ts +3 -0
  51. package/dist/components/Grid/tests/Grid.stories.js +39 -1
  52. package/dist/components/Hidden/Hidden.types.d.ts +4 -0
  53. package/dist/components/HiddenVisually/HiddenVisually.types.d.ts +1 -0
  54. package/dist/components/Hotkey/Hotkey.types.d.ts +4 -0
  55. package/dist/components/Icon/Icon.types.d.ts +6 -0
  56. package/dist/components/Image/Image.types.d.ts +15 -0
  57. package/dist/components/Link/Link.types.d.ts +7 -0
  58. package/dist/components/Loader/Loader.types.d.ts +5 -0
  59. package/dist/components/MenuItem/MenuItem.types.d.ts +13 -1
  60. package/dist/components/Modal/Modal.types.d.ts +19 -0
  61. package/dist/components/NumberField/NumberField.types.d.ts +10 -0
  62. package/dist/components/Overlay/Overlay.types.d.ts +13 -0
  63. package/dist/components/Pagination/Pagination.types.d.ts +11 -29
  64. package/dist/components/PinField/PinField.module.css +1 -1
  65. package/dist/components/PinField/PinField.types.d.ts +13 -0
  66. package/dist/components/PinField/tests/PinField.stories.d.ts +24 -3
  67. package/dist/components/PinField/tests/PinField.stories.js +194 -47
  68. package/dist/components/Popover/Popover.types.d.ts +4 -1
  69. package/dist/components/Progress/Progress.types.d.ts +9 -0
  70. package/dist/components/ProgressIndicator/ProgressIndicator.js +13 -84
  71. package/dist/components/ProgressIndicator/ProgressIndicator.module.css +1 -1
  72. package/dist/components/ProgressIndicator/ProgressIndicator.types.d.ts +8 -0
  73. package/dist/components/ProgressIndicator/tests/ProgressIndicator.stories.js +8 -1
  74. package/dist/components/Radio/Radio.types.d.ts +12 -0
  75. package/dist/components/RadioGroup/RadioGroup.types.d.ts +14 -0
  76. package/dist/components/Reshaped/Reshaped.css +1 -1
  77. package/dist/components/Reshaped/Reshaped.types.d.ts +12 -0
  78. package/dist/components/Resizable/Resizable.types.d.ts +7 -0
  79. package/dist/components/Scrim/Scrim.types.d.ts +6 -1
  80. package/dist/components/ScrollArea/ScrollArea.types.d.ts +7 -0
  81. package/dist/components/Select/Select.types.d.ts +27 -0
  82. package/dist/components/Skeleton/Skeleton.types.d.ts +2 -0
  83. package/dist/components/Slider/Slider.types.d.ts +56 -0
  84. package/dist/components/Stepper/Stepper.types.d.ts +13 -0
  85. package/dist/components/Switch/Switch.types.d.ts +16 -0
  86. package/dist/components/Table/Table.types.d.ts +29 -0
  87. package/dist/components/Tabs/Tabs.module.css +1 -1
  88. package/dist/components/Tabs/Tabs.types.d.ts +24 -0
  89. package/dist/components/Tabs/TabsItem.js +2 -2
  90. package/dist/components/Tabs/tests/Tabs.stories.js +6 -6
  91. package/dist/components/Text/Text.types.d.ts +12 -0
  92. package/dist/components/TextArea/TextArea.types.d.ts +17 -0
  93. package/dist/components/TextField/TextField.types.d.ts +29 -0
  94. package/dist/components/Theme/Theme.js +4 -1
  95. package/dist/components/Theme/Theme.types.d.ts +5 -0
  96. package/dist/components/Timeline/Timeline.types.d.ts +7 -0
  97. package/dist/components/Toast/Toast.types.d.ts +18 -0
  98. package/dist/components/ToggleButton/ToggleButton.types.d.ts +9 -0
  99. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.types.d.ts +8 -0
  100. package/dist/components/Tooltip/Tooltip.types.d.ts +5 -0
  101. package/dist/components/View/View.types.d.ts +56 -1
  102. package/dist/components/_private/Aligner/Aligner.types.d.ts +6 -0
  103. package/dist/themes/index.d.ts +1 -0
  104. package/dist/themes/index.js +1 -0
  105. package/package.json +47 -32
  106. package/LICENSE-SOURCE.md +0 -40
  107. package/dist/components/Grid/tests/Grid.test.stories.d.ts +0 -23
  108. package/dist/components/Grid/tests/Grid.test.stories.js +0 -42
  109. package/dist/components/PinField/tests/PinField.test.stories.d.ts +0 -29
  110. package/dist/components/PinField/tests/PinField.test.stories.js +0 -177
@@ -1,5 +1,7 @@
1
+ import { expect, fn, userEvent, waitFor } from "storybook/internal/test";
1
2
  import { Example } from "../../../utilities/storybook/index.js";
2
3
  import PinField from "../index.js";
4
+ import FormControl from "../../FormControl/index.js";
3
5
  export default {
4
6
  title: "Components/PinField",
5
7
  component: PinField,
@@ -9,54 +11,199 @@ export default {
9
11
  },
10
12
  },
11
13
  };
12
- export const base = () => (<Example>
13
- <Example.Item title="no value">
14
- <PinField name="pin" inputAttributes={{ "aria-label": "Pin" }}/>
15
- </Example.Item>
16
-
17
- <Example.Item title="defaultValue: 1234">
18
- <PinField name="pin2" defaultValue="1234" inputAttributes={{ "aria-label": "Pin" }}/>
19
- </Example.Item>
20
-
21
- <Example.Item title="value: 12">
22
- <PinField name="pin3" value="12" inputAttributes={{ "aria-label": "Pin" }}/>
23
- </Example.Item>
24
-
25
- <Example.Item title="defaultValue: 12, valueLength: 6">
26
- <PinField name="pin4" defaultValue="12" valueLength={6} inputAttributes={{ "aria-label": "Pin" }}/>
27
- </Example.Item>
28
-
29
- <Example.Item title="defaultValue: ab, charPattern: alphabetic">
30
- <PinField name="pin5" defaultValue="ab" pattern="alphabetic" inputAttributes={{ "aria-label": "Pin" }}/>
31
- </Example.Item>
32
-
33
- <Example.Item title="defaultValue: ab, charPattern: alphanumeric">
34
- <PinField name="pin6" defaultValue="ab" pattern="alphanumeric" inputAttributes={{ "aria-label": "Pin" }}/>
35
- </Example.Item>
36
- </Example>);
37
- export const variant = () => (<Example>
38
- <Example.Item title="variant: faded">
39
- <PinField name="pin" variant="faded" inputAttributes={{ "aria-label": "Pin" }}/>
40
- </Example.Item>
41
- </Example>);
42
- export const size = () => (<Example>
43
- <Example.Item title="size: small">
44
- <PinField name="pin" size="small" inputAttributes={{ "aria-label": "Pin" }}/>
45
- </Example.Item>
14
+ export const base = {
15
+ name: "base",
16
+ render: () => <PinField name="test-name" inputAttributes={{ "aria-label": "Label" }}/>,
17
+ play: async ({ canvas }) => {
18
+ const elInput = canvas.getByRole("textbox");
19
+ expect(elInput).toBeInTheDocument();
20
+ expect(elInput).toHaveAttribute("name", "test-name");
21
+ expect(elInput).toHaveAttribute("autocomplete", "one-time-code");
22
+ expect(elInput).toHaveAttribute("inputmode", "numeric");
23
+ },
24
+ };
25
+ export const variant = {
26
+ name: "variant",
27
+ render: () => (<Example>
28
+ <Example.Item title="variant: faded">
29
+ <PinField name="pin" variant="faded" inputAttributes={{ "aria-label": "Pin" }}/>
30
+ </Example.Item>
31
+ </Example>),
32
+ };
33
+ export const size = {
34
+ name: "size",
35
+ render: () => (<Example>
36
+ <Example.Item title="size: small">
37
+ <PinField name="pin" size="small" inputAttributes={{ "aria-label": "Pin" }}/>
38
+ </Example.Item>
46
39
 
47
- <Example.Item title="size: medium">
48
- <PinField name="pin" size="medium" inputAttributes={{ "aria-label": "Pin" }}/>
49
- </Example.Item>
40
+ <Example.Item title="size: medium">
41
+ <PinField name="pin" size="medium" inputAttributes={{ "aria-label": "Pin" }}/>
42
+ </Example.Item>
50
43
 
51
- <Example.Item title="size: large">
52
- <PinField name="pin" size="large" inputAttributes={{ "aria-label": "Pin" }}/>
53
- </Example.Item>
44
+ <Example.Item title="size: large">
45
+ <PinField name="pin" size="large" inputAttributes={{ "aria-label": "Pin" }}/>
46
+ </Example.Item>
54
47
 
55
- <Example.Item title="size: xlarge">
56
- <PinField name="pin" size="xlarge" inputAttributes={{ "aria-label": "Pin" }}/>
57
- </Example.Item>
48
+ <Example.Item title="size: xlarge">
49
+ <PinField name="pin" size="xlarge" inputAttributes={{ "aria-label": "Pin" }}/>
50
+ </Example.Item>
58
51
 
59
- <Example.Item title="size: responsive, s: medium, m+: xlarge">
60
- <PinField name="pin" size={{ s: "medium", m: "xlarge" }} inputAttributes={{ "aria-label": "Pin" }}/>
61
- </Example.Item>
62
- </Example>);
52
+ <Example.Item title="size: responsive, s: medium, m+: xlarge">
53
+ <PinField name="pin" size={{ s: "medium", m: "xlarge" }} inputAttributes={{ "aria-label": "Pin" }}/>
54
+ </Example.Item>
55
+ </Example>),
56
+ };
57
+ export const valueLength = {
58
+ name: "valueLength",
59
+ render: () => (<PinField name="test-name" valueLength={6} inputAttributes={{ "aria-label": "Label" }}/>),
60
+ play: async ({ canvas }) => {
61
+ const elInput = canvas.getByRole("textbox");
62
+ expect(elInput).toHaveAttribute("maxlength", "6");
63
+ },
64
+ };
65
+ export const defaultValue = {
66
+ name: "defaultValue, uncontrolled",
67
+ args: {
68
+ handleChange: fn(),
69
+ },
70
+ render: (args) => (<PinField name="test-name" onChange={args.handleChange} defaultValue="12" inputAttributes={{ "aria-label": "Label" }}/>),
71
+ play: async ({ canvas, args }) => {
72
+ const elInput = canvas.getByRole("textbox");
73
+ elInput.focus();
74
+ await userEvent.keyboard("3");
75
+ expect(args.handleChange).toHaveBeenCalledTimes(1);
76
+ expect(args.handleChange).toHaveBeenCalledWith({
77
+ value: "123",
78
+ name: "test-name",
79
+ event: expect.objectContaining({ target: elInput }),
80
+ });
81
+ expect(elInput).toHaveValue("123");
82
+ },
83
+ };
84
+ export const value = {
85
+ name: "value, controlled",
86
+ args: {
87
+ handleChange: fn(),
88
+ },
89
+ render: (args) => (<PinField name="test-name" onChange={args.handleChange} value="12" inputAttributes={{ "aria-label": "Label" }}/>),
90
+ play: async ({ canvas, args }) => {
91
+ const elInput = canvas.getByRole("textbox");
92
+ elInput.focus();
93
+ await userEvent.keyboard("3");
94
+ expect(args.handleChange).toHaveBeenCalledTimes(1);
95
+ expect(args.handleChange).toHaveBeenCalledWith({
96
+ value: "123",
97
+ name: "test-name",
98
+ event: expect.objectContaining({ target: elInput }),
99
+ });
100
+ expect(elInput).toHaveValue("12");
101
+ },
102
+ };
103
+ export const pattern = {
104
+ name: "pattern",
105
+ args: {
106
+ handleChange: fn(),
107
+ },
108
+ render: (args) => (<PinField name="test-name" pattern="alphabetic" defaultValue="ab" onChange={args.handleChange} inputAttributes={{ "aria-label": "Label" }}/>),
109
+ play: async ({ canvas, args }) => {
110
+ const elInput = canvas.getByRole("textbox");
111
+ elInput.focus();
112
+ await userEvent.keyboard("3");
113
+ expect(elInput).toHaveValue("ab");
114
+ expect(args.handleChange).toHaveBeenCalledTimes(0);
115
+ await userEvent.keyboard("c");
116
+ expect(elInput).toHaveValue("abc");
117
+ expect(args.handleChange).toHaveBeenCalledTimes(1);
118
+ },
119
+ };
120
+ export const className = {
121
+ name: "className, attributes",
122
+ render: () => (<div data-testid="root">
123
+ <PinField name="test-name" className="test-classname" attributes={{ id: "test-id" }} inputAttributes={{ "aria-label": "Label", id: "test-input-id" }}/>
124
+ </div>),
125
+ play: async ({ canvas }) => {
126
+ const root = canvas.getByTestId("root").firstChild;
127
+ const input = canvas.queryByLabelText("Label");
128
+ expect(root).toHaveClass("test-classname");
129
+ expect(root).toHaveAttribute("id", "test-id");
130
+ expect(input).toHaveAttribute("id", "test-input-id");
131
+ },
132
+ };
133
+ export const formControl = {
134
+ name: "test: with FormControl",
135
+ render: () => (<FormControl>
136
+ <FormControl.Label>Label</FormControl.Label>
137
+ <PinField name="test-name"/>
138
+ </FormControl>),
139
+ play: async ({ canvas }) => {
140
+ const elInput = canvas.getByRole("textbox");
141
+ expect(elInput).toHaveAccessibleName("Label");
142
+ },
143
+ };
144
+ export const keyboard = {
145
+ name: "test: keyboard navigation",
146
+ render: () => <PinField name="test-name" inputAttributes={{ "aria-label": "Label" }}/>,
147
+ play: async ({ canvas }) => {
148
+ const elInput = canvas.getByRole("textbox");
149
+ elInput.focus();
150
+ expect(elInput.selectionStart).toEqual(0);
151
+ expect(elInput.selectionEnd).toEqual(0);
152
+ await userEvent.keyboard("1");
153
+ await waitFor(() => {
154
+ expect(elInput.selectionStart).toEqual(1);
155
+ expect(elInput.selectionEnd).toEqual(1);
156
+ });
157
+ await userEvent.keyboard("234");
158
+ await waitFor(() => {
159
+ expect(elInput.selectionStart).toEqual(3);
160
+ expect(elInput.selectionEnd).toEqual(4);
161
+ });
162
+ // Move back to the first character
163
+ await userEvent.keyboard("{ArrowLeft/}");
164
+ await waitFor(() => {
165
+ expect(elInput.selectionStart).toEqual(2);
166
+ expect(elInput.selectionEnd).toEqual(3);
167
+ });
168
+ await userEvent.keyboard("{ArrowLeft/}");
169
+ await waitFor(() => {
170
+ expect(elInput.selectionStart).toEqual(1);
171
+ expect(elInput.selectionEnd).toEqual(2);
172
+ });
173
+ await userEvent.keyboard("{ArrowLeft}");
174
+ await waitFor(() => {
175
+ expect(elInput.selectionStart).toEqual(0);
176
+ expect(elInput.selectionEnd).toEqual(1);
177
+ });
178
+ // Move to the third character
179
+ await userEvent.keyboard("{ArrowRight}");
180
+ await waitFor(() => {
181
+ expect(elInput.selectionStart).toEqual(1);
182
+ expect(elInput.selectionEnd).toEqual(2);
183
+ });
184
+ await userEvent.keyboard("{ArrowRight}");
185
+ await waitFor(() => {
186
+ expect(elInput.selectionStart).toEqual(2);
187
+ expect(elInput.selectionEnd).toEqual(3);
188
+ });
189
+ expect(elInput).toHaveValue("1234");
190
+ await userEvent.keyboard("{backspace}");
191
+ expect(elInput).toHaveValue("124");
192
+ await waitFor(() => {
193
+ expect(elInput.selectionStart).toEqual(2);
194
+ expect(elInput.selectionEnd).toEqual(3);
195
+ });
196
+ // Switched to type mode
197
+ await userEvent.keyboard("{ArrowRight}");
198
+ await waitFor(() => {
199
+ expect(elInput.selectionStart).toEqual(3);
200
+ expect(elInput.selectionStart).toEqual(3);
201
+ });
202
+ // Can't move further
203
+ await userEvent.keyboard("{ArrowRight}");
204
+ await waitFor(() => {
205
+ expect(elInput.selectionStart).toEqual(3);
206
+ expect(elInput.selectionStart).toEqual(3);
207
+ });
208
+ },
209
+ };
@@ -1,9 +1,12 @@
1
1
  import type React from "react";
2
2
  import type { FlyoutProps, FlyoutInstance } from "../Flyout";
3
3
  export type Instance = FlyoutInstance;
4
- export type Props = Pick<FlyoutProps, "id" | "position" | "forcePosition" | "fallbackPositions" | "onOpen" | "onClose" | "width" | "trapFocusMode" | "active" | "defaultActive" | "contentGap" | "contentShift" | "instanceRef" | "triggerType" | "disableHideAnimation" | "disableContentHover" | "disableCloseOnOutsideClick" | "autoFocus" | "containerRef" | "initialFocusRef" | "originCoordinates"> & {
4
+ export type Props = Pick<FlyoutProps, "id" | "position" | "forcePosition" | "fallbackPositions" | "fallbackAdjustLayout" | "onOpen" | "onClose" | "width" | "trapFocusMode" | "active" | "defaultActive" | "contentGap" | "contentShift" | "instanceRef" | "triggerType" | "disableHideAnimation" | "disableContentHover" | "disableCloseOnOutsideClick" | "autoFocus" | "containerRef" | "initialFocusRef" | "originCoordinates"> & {
5
+ /** Node for inserting children */
5
6
  children?: React.ReactNode;
7
+ /** Content element padding, unit token multiplier */
6
8
  padding?: number;
9
+ /** Component elevation level */
7
10
  elevation?: "raised" | "overlay";
8
11
  /** @deprecated use Flyout utility instead, will be removed in v4 */
9
12
  variant?: "elevated" | "headless";
@@ -1,12 +1,21 @@
1
1
  import type * as G from "../../types/global";
2
2
  export type Props = {
3
+ /** Value of the progress bar controlling the size of the fill */
3
4
  value?: number;
5
+ /** Lower value boundary of the progress bar */
4
6
  max?: number;
7
+ /** Upper value boundary of the progress bar */
5
8
  min?: number;
9
+ /** Component size */
6
10
  size?: "small" | "medium";
11
+ /** Component color scheme */
7
12
  color?: "primary" | "critical" | "warning" | "positive" | "media";
13
+ /** Duration of the progress bar animation in milliseconds */
8
14
  duration?: number;
15
+ /** aria-label attribute for the root element */
9
16
  ariaLabel?: string;
17
+ /** Additional classname for the root element */
10
18
  className?: G.ClassName;
19
+ /** Additional attributes for the root element */
11
20
  attributes?: G.Attributes<"div">;
12
21
  };
@@ -1,30 +1,12 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import React from "react";
4
3
  import { classNames } from "../../utilities/props.js";
5
- import { onNextFrame } from "../../utilities/animation.js";
6
- import usePrevious from "../../hooks/_private/usePrevious.js";
7
4
  import s from "./ProgressIndicator.module.css";
8
- const MAX_RENDERED_ITEMS = 7;
9
- const BOUNDARY = (MAX_RENDERED_ITEMS - 1) / 2;
5
+ const VISIBLE_ITEMS = 7;
6
+ const HALF_ITEMS = Math.floor(VISIBLE_ITEMS / 2);
10
7
  const ProgressIndicator = (props) => {
11
8
  const { total, activeIndex = 0, color = "primary", ariaLabel, className, attributes } = props;
12
- const allItemsVisible = total < MAX_RENDERED_ITEMS;
13
- const firstRenderedIndex = React.useMemo(() => {
14
- if (allItemsVisible)
15
- return 0;
16
- if (activeIndex <= BOUNDARY)
17
- return 0;
18
- if (activeIndex >= total - 1 - BOUNDARY)
19
- return total - MAX_RENDERED_ITEMS;
20
- return activeIndex - BOUNDARY;
21
- }, [activeIndex, allItemsVisible, total]);
22
- const [startIndex, setStartIndex] = React.useState(firstRenderedIndex);
23
- const previousActiveIndex = usePrevious(activeIndex);
24
- const [shift, setShift] = React.useState(null);
25
- const [animated, setAnimatedState] = React.useState(true);
26
- const animatedRef = React.useRef(true);
27
- const rootClassName = classNames(s.root, className, shift && s[`--shift-${shift}`], color && s[`--color-${color}`], animated && s["--animated"]);
9
+ const rootClassName = classNames(s.root, className, color && s[`--color-${color}`]);
28
10
  const barAttributes = ariaLabel
29
11
  ? {
30
12
  "aria-label": ariaLabel,
@@ -34,69 +16,16 @@ const ProgressIndicator = (props) => {
34
16
  "aria-valuemax": total - 1,
35
17
  }
36
18
  : {};
37
- const setAnimated = (animated) => {
38
- setAnimatedState(animated);
39
- animatedRef.current = animated;
40
- };
41
- /**
42
- * After the shift transition, disable the animation and reset the items position
43
- */
44
- const handleTransitionEnd = (event) => {
45
- if (event.target !== event.currentTarget || event.pseudoElement)
46
- return;
47
- setAnimated(false);
48
- };
49
- React.useEffect(() => {
50
- if (animated)
51
- return;
52
- setShift(null);
53
- }, [animated]);
54
- React.useEffect(() => {
55
- if (shift)
56
- return;
57
- onNextFrame(() => setAnimated(true));
58
- }, [shift, firstRenderedIndex]);
59
- React.useEffect(() => {
60
- if (previousActiveIndex === activeIndex)
61
- return;
62
- const direction = previousActiveIndex && activeIndex < previousActiveIndex ? "start" : "end";
63
- const lastIndex = total - 1;
64
- const endThreshold = lastIndex - BOUNDARY;
65
- const isAtStartEdge = activeIndex < BOUNDARY || (direction === "end" && activeIndex === BOUNDARY);
66
- const isAtEndEdge = activeIndex > endThreshold || (direction === "start" && activeIndex === endThreshold);
67
- const isAtEdge = isAtStartEdge || isAtEndEdge;
68
- if (allItemsVisible || isAtEdge || !animatedRef.current) {
69
- setStartIndex(firstRenderedIndex);
70
- return;
71
- }
72
- setStartIndex(firstRenderedIndex);
73
- setShift(direction);
74
- }, [activeIndex, firstRenderedIndex, allItemsVisible, previousActiveIndex, total]);
75
- const renderItems = () => {
76
- let selectionDelta = 0;
77
- if (shift === "start")
78
- selectionDelta = -1;
79
- if (shift === "end")
80
- selectionDelta = 1;
81
- const itemAmount = Math.min(MAX_RENDERED_ITEMS, total);
82
- const items = [];
83
- const lastIndex = total - 1;
84
- const activeVisibleIndex = activeIndex - startIndex + selectionDelta;
85
- const rightExtra = Math.max(BOUNDARY - activeIndex, 0);
86
- const leftExtra = Math.max(BOUNDARY - (lastIndex - activeIndex), 0);
87
- const rightModifierIndex = activeVisibleIndex + rightExtra + 1;
88
- const leftModifierIndex = activeVisibleIndex - leftExtra - 1;
89
- for (let i = 0; i < itemAmount; i += 1) {
90
- const isActive = i === activeVisibleIndex;
91
- const isSmall = i === rightModifierIndex + 1 || i === leftModifierIndex - 1;
92
- const isSmaller = i === rightModifierIndex + 2 || i === leftModifierIndex - 2;
93
- const isHidden = i > rightModifierIndex + 2 || i < leftModifierIndex - 2;
94
- const itemClassName = classNames(s.item, isActive && s["item--active"], !allItemsVisible && isSmall && s["item--variant-secondary"], !allItemsVisible && isSmaller && s["item--variant-tertiary"], !allItemsVisible && isHidden && s["item--variant-hidden"]);
95
- items.push(_jsx("div", { className: itemClassName }, i));
96
- }
97
- return items;
98
- };
99
- return (_jsx("div", { ...attributes, className: rootClassName, children: _jsx("div", { ...barAttributes, className: s.container, onTransitionEnd: handleTransitionEnd, children: renderItems() }) }));
19
+ const transformIndex = total > VISIBLE_ITEMS
20
+ ? Math.min(total - VISIBLE_ITEMS, Math.max(0, activeIndex - HALF_ITEMS))
21
+ : 0;
22
+ return (_jsx("div", { ...attributes, className: rootClassName, children: _jsx("div", { ...barAttributes, className: s.container, style: {
23
+ "--rs-progress-indicator-mod": transformIndex,
24
+ }, children: Array.from({ length: total }).map((_, i) => {
25
+ const itemClassName = classNames(s.item, i === activeIndex && s["item--active"], (i < activeIndex - (HALF_ITEMS - 1) || i > activeIndex + (HALF_ITEMS - 1)) &&
26
+ s["item--variant-secondary"]);
27
+ return _jsx("div", { className: itemClassName }, i);
28
+ }) }) }));
100
29
  };
101
30
  ProgressIndicator.displayName = "ProgressIndicator";
102
31
  export default ProgressIndicator;
@@ -1 +1 @@
1
- .root{line-height:0}.container{display:inline-flex;position:relative;vertical-align:top}.container:after,.container:before{content:"";inset-inline-start:calc(var(--rs-unit-x4) * -1);opacity:0;position:absolute}.container:after,.container:before,.item{background:var(--rs-color-background-neutral);border-radius:var(--rs-radius-circular);height:var(--rs-unit-x2);width:var(--rs-unit-x2)}.item{margin-inline-start:var(--rs-unit-x2)}.item:first-child{margin-inline-start:0}.item.item--active{background:var(--rs-color-background-primary);transform:scale(1.2)}.item.item--variant-secondary{opacity:.6}.item.item--variant-tertiary{opacity:.3}.item.item--variant-hidden{opacity:0}.--color-media .container:after,.--color-media .container:before,.--color-media .item{background:var(--rs-color-white)}.--color-media .item{opacity:.6}.--color-media .item.item--active{opacity:1}.--color-media .item.item--variant-secondary{opacity:.3}.--color-media .item.item--variant-tertiary{opacity:.1}.--color-media .item.item--variant-hidden{opacity:0}.--shift-start .container,[dir=rtl] .--shift-end .container{transform:translateX(var(--rs-unit-x4))}.--shift-end .container,[dir=rtl] .--shift-start .container{transform:translateX(calc(var(--rs-unit-x4) * -1))}.--shift-end .container:after,.--shift-start .container:before{opacity:.3}.--shift-end.--color-media .container:after,.--shift-start.--color-media .container:before{opacity:.1}.--shift-start .container:before{inset-inline-end:auto;inset-inline-start:calc(var(--rs-unit-x4) * -1)}.--shift-end .container:after{inset-inline-end:calc(var(--rs-unit-x4) * -1);inset-inline-start:auto}.--animated .container,.--animated .container:after,.--animated .container:before,.--animated .item{transition:var(--rs-duration-slow) var(--rs-easing-decelerate);transition-property:transform,opacity,background-color}
1
+ .root{box-sizing:initial;line-height:0;margin-inline:calc(var(--rs-unit-x4) * -1);mask-image:linear-gradient(to right,transparent 0,#000 var(--rs-unit-x4),#000 calc(100% - var(--rs-unit-x4)),transparent 100%);max-width:calc(var(--rs-unit-x2) * 15);overflow:hidden;padding-inline:var(--rs-unit-x4)}.container{display:inline-flex;position:relative;transform:translateX(calc(var(--rs-unit-x4) * -1 * var(--rs-progress-indicator-mod)));transition:var(--rs-duration-slow) var(--rs-easing-decelerate);transition-property:transform;vertical-align:top}.item{background:var(--rs-color-background-neutral);border-radius:var(--rs-radius-circular);height:var(--rs-unit-x2);margin-inline-start:var(--rs-unit-x2);transform:translateZ(0);transition:var(--rs-duration-slow) var(--rs-easing-decelerate);transition-property:transform,opacity,background-color,width;width:var(--rs-unit-x2)}.item:first-child{margin-inline-start:0}.item.item--active{background:var(--rs-color-background-primary);width:var(--rs-unit-x6)}.item.item--variant-secondary{opacity:.5}.--color-media .item{background:var(--rs-color-white);opacity:.5}.--color-media .item.item--active{opacity:1}.--color-media .item.item--variant-secondary{opacity:.25}
@@ -1,9 +1,17 @@
1
1
  import type * as G from "../../types/global";
2
2
  export type Props = {
3
+ /** Total amount of progress indicator dots */
3
4
  total: number;
5
+ /** Index of the active progress indicator dot */
4
6
  activeIndex?: number;
7
+ /** Component size */
8
+ size?: "small" | "medium";
9
+ /** Component color scheme */
5
10
  color?: "primary" | "media";
11
+ /** aria-label attribute for the root element */
6
12
  ariaLabel?: string;
13
+ /** Additional classname for the root element */
7
14
  className?: G.ClassName;
15
+ /** Additional attributes for the root element */
8
16
  attributes?: G.Attributes<"div">;
9
17
  };
@@ -36,7 +36,14 @@ export const base = {
36
36
  </Button>
37
37
  <Text weight="medium">Index: {activeIndex}</Text>
38
38
  </View>
39
- <ProgressIndicator total={total} activeIndex={activeIndex}/>
39
+
40
+ <View borderRadius="medium" overflow="hidden" width="300px">
41
+ <Scrim position="bottom" backgroundSlot={<View aspectRatio={16 / 9} backgroundColor="neutral-faded"/>}>
42
+ <View align="center">
43
+ <ProgressIndicator total={total} activeIndex={activeIndex} color="media"/>
44
+ </View>
45
+ </Scrim>
46
+ </View>
40
47
  </View>
41
48
  </Example.Item>
42
49
  </Example>);
@@ -1,17 +1,29 @@
1
1
  import type React from "react";
2
2
  import type * as G from "../../types/global";
3
3
  type BaseProps = {
4
+ /** Node for inserting children */
4
5
  children?: React.ReactNode;
6
+ /** Name of the input element */
5
7
  name?: string;
8
+ /** Disable the form field from the form submission */
6
9
  disabled?: boolean;
10
+ /** Indicate that the form field has an error */
7
11
  hasError?: boolean;
12
+ /** Value of the input element */
8
13
  value: string;
14
+ /** Component size */
9
15
  size?: G.Responsive<"small" | "medium" | "large">;
16
+ /** Callback when the input value changes */
10
17
  onChange?: G.ChangeHandler<boolean>;
18
+ /** Callback when the input is focused */
11
19
  onFocus?: (e: React.FocusEvent) => void;
20
+ /** Callback when the input is blurred */
12
21
  onBlur?: (e: React.FocusEvent) => void;
22
+ /** Additional classname for the root element */
13
23
  className?: G.ClassName;
24
+ /** Additional attributes for the root element */
14
25
  attributes?: G.Attributes<"label">;
26
+ /** Additional attributes for the input element */
15
27
  inputAttributes?: G.Attributes<"input">;
16
28
  };
17
29
  export type ControlledProps = BaseProps & {
@@ -2,19 +2,33 @@ import type React from "react";
2
2
  import type * as G from "../../types/global";
3
3
  import type { RadioProps } from "../Radio";
4
4
  type BaseProps = {
5
+ /** Unique identifier for the radio group */
5
6
  id?: string;
7
+ /** Node for inserting children */
6
8
  children?: React.ReactNode;
9
+ /** Disable the form field from the form submission */
7
10
  disabled?: boolean;
11
+ /** Name of the input element */
8
12
  name: string;
13
+ /** Indicate that the form field has an error */
9
14
  hasError?: boolean;
15
+ /** Callback when the input value changes */
10
16
  onChange?: G.ChangeHandler<string>;
17
+ /** Additional classname for the root element */
18
+ className?: G.ClassName;
19
+ /** Additional attributes for the root element */
20
+ attributes?: G.Attributes<"div">;
11
21
  };
12
22
  export type ControlledProps = BaseProps & {
23
+ /** Value of the input element, enables controlled mode */
13
24
  value: string | null;
25
+ /** Default value of the input element, enables uncontrolled mode */
14
26
  defaultValue?: never;
15
27
  };
16
28
  export type UncontrolledProps = BaseProps & {
29
+ /** Value of the input element, enables controlled mode */
17
30
  value?: never;
31
+ /** Default value of the input element, enables uncontrolled mode */
18
32
  defaultValue?: string;
19
33
  };
20
34
  export type Props = ControlledProps | UncontrolledProps;
@@ -1 +1 @@
1
- @layer rs.reset{[data-rs-theme]{--rs-radius-circular:9999px;--rs-shadow-border-faded:0px 0px 0px 1px var(--rs-color-border-neutral-faded)}[data-rs-theme] blockquote,[data-rs-theme] body,[data-rs-theme] dd,[data-rs-theme] dl,[data-rs-theme] figcaption,[data-rs-theme] figure,[data-rs-theme] h1,[data-rs-theme] h2,[data-rs-theme] h3,[data-rs-theme] h4,[data-rs-theme] h5,[data-rs-theme] h6,[data-rs-theme] li,[data-rs-theme] ol,[data-rs-theme] p,[data-rs-theme] ul{margin:0;padding:0}[data-rs-theme] ol[class],[data-rs-theme] ul[class]{list-style:none}[data-rs-theme] textarea{resize:vertical}[data-rs-theme] table{border-collapse:collapse;border-spacing:0}[data-rs-theme] fieldset{border:0;margin:0;padding:0}[data-rs-theme] img{display:block;max-width:100%}[data-rs-theme] button,[data-rs-theme] input,[data-rs-theme] select,[data-rs-theme] textarea{font:inherit}[data-rs-theme] option{background:var(--rs-color-background-elevation-base)}[data-rs-theme] label{cursor:pointer}[data-rs-theme] input::placeholder,[data-rs-theme] textarea::placeholder{color:var(--rs-color-foreground-disabled)}html[data-rs-theme]{-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;font-size:100%;text-rendering:optimizelegibility;touch-action:manipulation}[data-rs-theme] *{box-sizing:border-box}[data-rs-theme] body,html[data-rs-theme]{background:var(--rs-color-background-page);color:var(--rs-color-foreground-neutral);height:100%;scroll-behavior:smooth}}[data-rs-theme] body,[data-rs-theme]:not(html){font-family:var(--rs-font-family-body);font-size:var(--rs-font-size-body-3);font-weight:var(--rs-font-weight-regular);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3)}[data-rs-color-mode=light]{color-scheme:light}[data-rs-color-mode=dark]{color-scheme:dark}@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}[data-rs-no-transition] *,[data-rs-no-transition] :after,[data-rs-no-transition] :before{transition:none!important}
1
+ @layer rs.reset{[data-rs-theme]{--rs-radius-circular:9999px;--rs-shadow-border-faded:0px 0px 0px 1px var(--rs-color-border-neutral-faded)}[data-rs-theme] blockquote,[data-rs-theme] body,[data-rs-theme] dd,[data-rs-theme] dl,[data-rs-theme] figcaption,[data-rs-theme] figure,[data-rs-theme] h1,[data-rs-theme] h2,[data-rs-theme] h3,[data-rs-theme] h4,[data-rs-theme] h5,[data-rs-theme] h6,[data-rs-theme] li,[data-rs-theme] ol,[data-rs-theme] p,[data-rs-theme] ul{margin:0;padding:0}[data-rs-theme] ol[class],[data-rs-theme] ul[class]{list-style:none}[data-rs-theme] textarea{resize:vertical}[data-rs-theme] table{border-collapse:collapse;border-spacing:0}[data-rs-theme] fieldset{border:0;margin:0;padding:0}[data-rs-theme] img{display:block;max-width:100%}[data-rs-theme] button,[data-rs-theme] input,[data-rs-theme] select,[data-rs-theme] textarea{font:inherit}[data-rs-theme] option{background:var(--rs-color-background-elevation-base)}[data-rs-theme] label{cursor:pointer}[data-rs-theme] input::placeholder,[data-rs-theme] textarea::placeholder{color:var(--rs-color-foreground-disabled)}html[data-rs-theme]{-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;font-size:100%;text-rendering:optimizelegibility;touch-action:manipulation}[data-rs-theme] *{box-sizing:border-box}[data-rs-theme] body,html[data-rs-theme]{background:var(--rs-color-background-page);color:var(--rs-color-foreground-neutral);min-height:100vh;scroll-behavior:smooth}}[data-rs-theme] body,[data-rs-theme]:not(html){font-family:var(--rs-font-family-body);font-size:var(--rs-font-size-body-3);font-weight:var(--rs-font-weight-regular);letter-spacing:var(--rs-letter-spacing-body-3);line-height:var(--rs-line-height-body-3)}[data-rs-color-mode=light]{color-scheme:light}[data-rs-color-mode=dark]{color-scheme:dark}@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.01ms!important}}[data-rs-no-transition] *,[data-rs-no-transition] :after,[data-rs-no-transition] :before{transition:none!important}
@@ -3,14 +3,26 @@ import type { GlobalColorModeProps, ThemeProps } from "../Theme";
3
3
  import type { ToastProviderProps } from "../Toast";
4
4
  import type * as G from "../../types/global";
5
5
  export type Props = {
6
+ /** Node for inserting children */
6
7
  children?: React.ReactNode;
8
+ /** Theme of the application, enables controlled mode */
7
9
  theme?: NonNullable<ThemeProps["name"]>;
10
+ /** Default theme of the application, enables uncontrolled mode */
8
11
  defaultTheme?: NonNullable<ThemeProps["defaultName"]>;
12
+ /** Default content direction of the application */
9
13
  defaultRTL?: boolean;
14
+ /** Color mode of the application, enables controlled mode */
10
15
  colorMode?: GlobalColorModeProps["mode"];
16
+ /** Default color mode of the application, enables uncontrolled mode */
11
17
  defaultColorMode?: GlobalColorModeProps["defaultMode"];
18
+ /** Default viewport size of the application */
12
19
  defaultViewport?: G.Viewport;
20
+ /** Global options for the ToastProvider */
13
21
  toastOptions?: ToastProviderProps["options"];
22
+ /** Enable scoped mode for applications not using Reshaped provider at the application root */
14
23
  scoped?: boolean;
24
+ /** Additional classname for the root element */
15
25
  className?: G.ClassName;
26
+ /** Additional attributes for the root element */
27
+ attributes?: G.Attributes<"div">;
16
28
  };
@@ -2,19 +2,26 @@ import type React from "react";
2
2
  import type { ViewProps } from "../View";
3
3
  import type { UseDragCallbackArgs } from "../../hooks/_private/useDrag";
4
4
  export type Props = {
5
+ /** Component render variant */
5
6
  variant?: "bordered" | "borderless";
7
+ /** Component content direction with the resize handle rendered in between the chidlren */
6
8
  direction?: Extract<ViewProps["direction"], "row" | "column">;
7
9
  } & Pick<ViewProps, "children" | "className" | "attributes" | "height" | "gap">;
8
10
  export type ItemProps = {
11
+ /** Node for inserting content */
9
12
  children: React.ReactNode;
13
+ /** Minimum size of the resizable pane */
10
14
  minSize?: `${number}px`;
15
+ /** Maximum size of the resizable pane */
11
16
  maxSize?: `${number}px`;
17
+ /** Default size of the resizable pane */
12
18
  defaultSize?: `${number}px`;
13
19
  };
14
20
  export type PrivateItemProps = ItemProps & {
15
21
  index: number;
16
22
  };
17
23
  export type HandleProps = {
24
+ /** Render function for custom resize handles with attributes and props passed as arguments */
18
25
  children?: (attributes: {
19
26
  ref: React.RefObject<HTMLButtonElement | null>;
20
27
  }, props: Pick<Props, "direction"> & {
@@ -1,11 +1,16 @@
1
1
  import React from "react";
2
2
  import type * as G from "../../types/global";
3
3
  export type Props = {
4
+ /** Node for inserting content */
4
5
  children?: React.ReactNode;
6
+ /** Node for inserting background content behind the scrim */
5
7
  backgroundSlot?: React.ReactNode;
8
+ /** Component content position */
6
9
  position?: "full" | "top" | "bottom" | "start" | "end";
7
- fill?: boolean;
10
+ /** Additional classname for the scrim element */
8
11
  scrimClassName?: G.ClassName;
12
+ /** Additional classname for the root element */
9
13
  className?: G.ClassName;
14
+ /** Additional attributes for the root element */
10
15
  attributes?: G.Attributes<"div">;
11
16
  };
@@ -1,12 +1,19 @@
1
1
  import type React from "react";
2
2
  import type * as G from "../../types/global";
3
3
  export type Props = {
4
+ /** Node for inserting content */
4
5
  children: React.ReactNode;
6
+ /** Scrollbar visibility behavior based on the user interaction */
5
7
  scrollbarDisplay?: "visible" | "hover" | "hidden";
8
+ /** Callback when the scroll area is scrolled */
6
9
  onScroll?: (args: G.Coordinates) => void;
10
+ /** Height of the scroll area, literal css value or unit token multiplier */
7
11
  height?: G.Responsive<string | number>;
12
+ /** Maximum height of the scroll area, literal css value or unit token multiplier */
8
13
  maxHeight?: G.Responsive<string | number>;
14
+ /** Additional classname for the root element */
9
15
  className?: G.ClassName;
16
+ /** Additional attributes for the root element */
10
17
  attributes?: G.Attributes<"div">;
11
18
  };
12
19
  export type BarProps = {