@workday/canvas-kit-labs-react 15.0.0-alpha.0056-next.0 → 15.0.0-alpha.0064-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/commonjs/ai-ingress-button/lib/AIIngressButton.js +5 -5
  2. package/dist/commonjs/index.d.ts +1 -0
  3. package/dist/commonjs/index.d.ts.map +1 -1
  4. package/dist/commonjs/index.js +1 -0
  5. package/dist/commonjs/search-form/lib/SearchForm.js +14 -14
  6. package/dist/commonjs/side-panel/index.d.ts +4 -0
  7. package/dist/commonjs/side-panel/index.d.ts.map +1 -0
  8. package/dist/commonjs/side-panel/index.js +19 -0
  9. package/dist/commonjs/side-panel/lib/SidePanel.d.ts +205 -0
  10. package/dist/commonjs/side-panel/lib/SidePanel.d.ts.map +1 -0
  11. package/dist/commonjs/side-panel/lib/SidePanel.js +64 -0
  12. package/dist/commonjs/side-panel/lib/SidePanelToggleButton.d.ts +95 -0
  13. package/dist/commonjs/side-panel/lib/SidePanelToggleButton.d.ts.map +1 -0
  14. package/dist/commonjs/side-panel/lib/SidePanelToggleButton.js +65 -0
  15. package/dist/commonjs/side-panel/lib/useSidePanelModel.d.ts +514 -0
  16. package/dist/commonjs/side-panel/lib/useSidePanelModel.d.ts.map +1 -0
  17. package/dist/commonjs/side-panel/lib/useSidePanelModel.js +134 -0
  18. package/dist/commonjs/version/lib/version.js +1 -1
  19. package/dist/es6/ai-ingress-button/lib/AIIngressButton.js +5 -5
  20. package/dist/es6/index.d.ts +1 -0
  21. package/dist/es6/index.d.ts.map +1 -1
  22. package/dist/es6/index.js +1 -0
  23. package/dist/es6/search-form/lib/SearchForm.js +14 -14
  24. package/dist/es6/side-panel/index.d.ts +4 -0
  25. package/dist/es6/side-panel/index.d.ts.map +1 -0
  26. package/dist/es6/side-panel/index.js +3 -0
  27. package/dist/es6/side-panel/lib/SidePanel.d.ts +205 -0
  28. package/dist/es6/side-panel/lib/SidePanel.d.ts.map +1 -0
  29. package/dist/es6/side-panel/lib/SidePanel.js +61 -0
  30. package/dist/es6/side-panel/lib/SidePanelToggleButton.d.ts +95 -0
  31. package/dist/es6/side-panel/lib/SidePanelToggleButton.d.ts.map +1 -0
  32. package/dist/es6/side-panel/lib/SidePanelToggleButton.js +62 -0
  33. package/dist/es6/side-panel/lib/useSidePanelModel.d.ts +514 -0
  34. package/dist/es6/side-panel/lib/useSidePanelModel.d.ts.map +1 -0
  35. package/dist/es6/side-panel/lib/useSidePanelModel.js +108 -0
  36. package/dist/es6/version/lib/version.js +1 -1
  37. package/index.ts +1 -0
  38. package/package.json +4 -4
  39. package/side-panel/index.ts +3 -0
  40. package/side-panel/lib/SidePanel.tsx +131 -0
  41. package/side-panel/lib/SidePanelToggleButton.tsx +177 -0
  42. package/side-panel/lib/useSidePanelModel.ts +128 -0
  43. package/side-panel/package.json +6 -0
@@ -0,0 +1,131 @@
1
+ import * as React from 'react';
2
+ import {createContainer, createElemPropsHook} from '@workday/canvas-kit-react/common';
3
+ import {createStencil, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
4
+ import {system} from '@workday/canvas-tokens-web';
5
+ import {useSidePanelModel} from './useSidePanelModel';
6
+ import {SidePanelToggleButton} from './SidePanelToggleButton';
7
+
8
+ /**
9
+ * Adds the necessary props to the SidePanel container element.
10
+ * This includes the `id` and `aria-labelledby` attributes for accessibility.
11
+ */
12
+ export const useSidePanelContainer = createElemPropsHook(useSidePanelModel)(({state, events}) => {
13
+ return {
14
+ id: state.panelId,
15
+ 'aria-labelledby': state.labelId,
16
+ onTransitionEnd: events.handleAnimationEnd,
17
+ };
18
+ });
19
+
20
+ export type SidePanelVariant = 'standard' | 'alternate';
21
+
22
+ export interface SidePanelProps {
23
+ /**
24
+ * The width of the component (in `px` if it's a `number`) when it is collapsed.
25
+ *
26
+ * @default 64
27
+ */
28
+ collapsedWidth?: number | string;
29
+ /**
30
+ * The width of the component (in `px` if it's a `number`) when it is expanded.
31
+ *
32
+ * @default 320
33
+ */
34
+ expandedWidth?: number | string;
35
+ /**
36
+ * The style variant of the side panel. 'standard' uses a lighter gray background (`system.color.bg.alt.softer`), no depth. 'alternate' uses a white background with depth (`system.color.bg.default` and level 5 depth).
37
+ *
38
+ * @default 'standard'
39
+ */
40
+ variant?: SidePanelVariant;
41
+ children?: React.ReactNode;
42
+ }
43
+
44
+ export const panelStencil = createStencil({
45
+ vars: {
46
+ expandedWidth: '',
47
+ collapsedWidth: '',
48
+ },
49
+ base: () => ({
50
+ overflow: 'hidden',
51
+ position: 'relative',
52
+ height: '100%',
53
+ outline: `${px2rem(1)} solid transparent`,
54
+ transition: 'width ease-out 200ms, max-width ease-out 200ms',
55
+ }),
56
+ modifiers: {
57
+ variant: {
58
+ alternate: {
59
+ backgroundColor: system.color.bg.default,
60
+ boxShadow: system.depth[5],
61
+ },
62
+ standard: {
63
+ backgroundColor: system.color.bg.alt.softer,
64
+ },
65
+ },
66
+ expanded: {
67
+ expanded: ({expandedWidth}) => ({
68
+ width: expandedWidth,
69
+ maxWidth: expandedWidth,
70
+ }),
71
+ collapsed: ({collapsedWidth}) => ({
72
+ width: collapsedWidth,
73
+ maxWidth: collapsedWidth,
74
+ }),
75
+ expanding: ({expandedWidth}) => ({
76
+ width: expandedWidth,
77
+ maxWidth: expandedWidth,
78
+ }),
79
+ collapsing: ({collapsedWidth}) => ({
80
+ width: collapsedWidth,
81
+ maxWidth: collapsedWidth,
82
+ }),
83
+ },
84
+ },
85
+ });
86
+
87
+ export const SidePanel = createContainer('section')({
88
+ displayName: 'SidePanel',
89
+ modelHook: useSidePanelModel,
90
+ elemPropsHook: useSidePanelContainer,
91
+ subComponents: {
92
+ /**
93
+ * `SidePanel.ToggleButton` is a control that toggles between expanded and collapsed states.
94
+ * It must be used within the `SidePanel` component as a child. For accessibility purposes,
95
+ * it should be the first focusable element in the panel.
96
+ *
97
+ * The button automatically receives `aria-controls`, `aria-expanded`, and `aria-labelledby`
98
+ * attributes from the model.
99
+ */
100
+ ToggleButton: SidePanelToggleButton,
101
+ },
102
+ })<SidePanelProps>(
103
+ (
104
+ {
105
+ collapsedWidth = 64,
106
+ expandedWidth = 320,
107
+ variant = 'standard',
108
+ children,
109
+ ...elemProps
110
+ }: SidePanelProps,
111
+ Element,
112
+ model
113
+ ) => {
114
+ return (
115
+ <Element
116
+ {...handleCsProp(elemProps, [
117
+ panelStencil({
118
+ expanded: model.state.transitionState,
119
+ variant,
120
+ expandedWidth:
121
+ typeof expandedWidth === 'number' ? px2rem(expandedWidth) : expandedWidth,
122
+ collapsedWidth:
123
+ typeof collapsedWidth === 'number' ? px2rem(collapsedWidth) : collapsedWidth,
124
+ }),
125
+ ])}
126
+ >
127
+ {children}
128
+ </Element>
129
+ );
130
+ }
131
+ );
@@ -0,0 +1,177 @@
1
+ import * as React from 'react';
2
+ import {
3
+ createElemPropsHook,
4
+ createSubcomponent,
5
+ ExtractProps,
6
+ } from '@workday/canvas-kit-react/common';
7
+ import {TertiaryButton} from '@workday/canvas-kit-react/button';
8
+ import {transformationImportIcon} from '@workday/canvas-system-icons-web';
9
+ import {Tooltip, TooltipProps} from '@workday/canvas-kit-react/tooltip';
10
+ import {useSidePanelModel} from './useSidePanelModel';
11
+ import {createStencil, handleCsProp} from '@workday/canvas-kit-styling';
12
+ import {system} from '@workday/canvas-tokens-web';
13
+
14
+ export interface SidePanelToggleButtonProps extends ExtractProps<typeof TertiaryButton> {
15
+ /**
16
+ * The tooltip text to expand the side panel
17
+ */
18
+ tooltipTextExpand?: string;
19
+ /**
20
+ * The tooltip text to collapse the side panel
21
+ */
22
+ tooltipTextCollapse?: string;
23
+ tooltipProps?: Omit<TooltipProps, 'children'>;
24
+ }
25
+
26
+ export const sidePanelToggleButtonStencil = createStencil({
27
+ base: {
28
+ position: 'absolute',
29
+ top: system.space.x6,
30
+ width: system.space.x8,
31
+ insetInlineEnd: system.space.x4,
32
+ },
33
+ modifiers: {
34
+ state: {
35
+ collapsing: {
36
+ margin: 0,
37
+ transform: `scaleX(1)`,
38
+ ':dir(rtl)': {
39
+ transform: `scaleX(-1)`,
40
+ },
41
+ },
42
+ collapsed: {
43
+ margin: 'auto',
44
+ insetInlineStart: 0,
45
+ insetInlineEnd: 0,
46
+ transform: `scaleX(1)`,
47
+ ':dir(rtl)': {
48
+ transform: `scaleX(-1)`,
49
+ },
50
+ },
51
+ expanded: {
52
+ margin: 0,
53
+ transform: `scaleX(-1)`,
54
+ ':dir(rtl)': {
55
+ transform: `scaleX(1)`,
56
+ },
57
+ },
58
+ expanding: {
59
+ margin: 0,
60
+ transform: `scaleX(-1)`,
61
+ ':dir(rtl)': {
62
+ transform: `scaleX(1)`,
63
+ },
64
+ },
65
+ },
66
+ origin: {
67
+ start: {},
68
+ end: {
69
+ transform: `scaleX(1)`,
70
+ ':dir(rtl)': {
71
+ transform: `scaleX(-1)`,
72
+ },
73
+ },
74
+ },
75
+ },
76
+
77
+ compound: [
78
+ {
79
+ modifiers: {state: 'collapsed', origin: 'end'},
80
+ styles: {
81
+ transform: `scaleX(-1)`,
82
+ ':dir(rtl)': {
83
+ transform: `scaleX(1)`,
84
+ },
85
+ },
86
+ },
87
+ {
88
+ modifiers: {state: 'collapsing', origin: 'end'},
89
+ styles: {
90
+ transform: `scaleX(-1)`,
91
+ insetInlineStart: system.space.x4,
92
+ ':dir(rtl)': {
93
+ transform: `scaleX(1)`,
94
+ insetInlineEnd: system.space.x4,
95
+ },
96
+ },
97
+ },
98
+ {
99
+ modifiers: {state: 'expanded', origin: 'end'},
100
+ styles: {
101
+ transform: `scaleX(1)`,
102
+ insetInlineStart: system.space.x4,
103
+ ':dir(rtl)': {
104
+ transform: `scaleX(-1)`,
105
+ insetInlineEnd: system.space.x4,
106
+ },
107
+ },
108
+ },
109
+ {
110
+ modifiers: {state: 'expanding', origin: 'end'},
111
+ styles: {
112
+ transform: `scaleX(1)`,
113
+ insetInlineStart: system.space.x4,
114
+ ':dir(rtl)': {
115
+ transform: `scaleX(-1)`,
116
+ insetInlineEnd: system.space.x4,
117
+ },
118
+ },
119
+ },
120
+ ],
121
+ });
122
+
123
+ export const useSidePanelToggleButtonElemProps = createElemPropsHook(useSidePanelModel)(
124
+ ({state}) => {
125
+ return {
126
+ 'aria-controls': state.panelId,
127
+ 'aria-expanded': state.transitionState === 'expanded',
128
+ 'aria-labelledby': state.labelId,
129
+ };
130
+ }
131
+ );
132
+
133
+ export const SidePanelToggleButton = createSubcomponent('button')({
134
+ displayName: 'SidePanel.ToggleButton',
135
+ modelHook: useSidePanelModel,
136
+ elemPropsHook: useSidePanelToggleButtonElemProps,
137
+ })(
138
+ (
139
+ {
140
+ variant = undefined,
141
+ icon = transformationImportIcon,
142
+ tooltipTextExpand = 'Expand',
143
+ tooltipTextCollapse = 'Collapse',
144
+ tooltipProps,
145
+ ...elemProps
146
+ }: SidePanelToggleButtonProps,
147
+ Element,
148
+ model
149
+ ) => {
150
+ return (
151
+ <Tooltip
152
+ type="muted"
153
+ {...tooltipProps}
154
+ title={
155
+ model.state.transitionState === 'collapsed' ? tooltipTextExpand : tooltipTextCollapse
156
+ }
157
+ >
158
+ <TertiaryButton
159
+ icon={icon}
160
+ as={Element}
161
+ variant={variant}
162
+ {...handleCsProp(
163
+ elemProps,
164
+ sidePanelToggleButtonStencil({
165
+ state: model.state.transitionState,
166
+ origin: model.state.origin,
167
+ })
168
+ )}
169
+ onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
170
+ elemProps.onClick?.(event);
171
+ model.events.handleAnimationStart();
172
+ }}
173
+ />
174
+ </Tooltip>
175
+ );
176
+ }
177
+ );
@@ -0,0 +1,128 @@
1
+ import {createModelHook, useUniqueId} from '@workday/canvas-kit-react/common';
2
+ import * as React from 'react';
3
+
4
+ /**
5
+ * The transition states of the SidePanel during expand/collapse animations.
6
+ * - `expanded`: Panel is fully expanded
7
+ * - `expanding`: Panel is animating from collapsed to expanded
8
+ * - `collapsed`: Panel is fully collapsed
9
+ * - `collapsing`: Panel is animating from expanded to collapsed
10
+ */
11
+ export type SidePanelTransitionStates = 'collapsed' | 'collapsing' | 'expanded' | 'expanding';
12
+
13
+ export const useSidePanelModel = createModelHook({
14
+ defaultConfig: {
15
+ /**
16
+ * The initial transition state of the SidePanel.
17
+ * @default 'expanded'
18
+ */
19
+ initialTransitionState: 'expanded' as SidePanelTransitionStates,
20
+ /**
21
+ * Which side the SidePanel originates from. Uses logical properties for RTL support.
22
+ * - `start`: Left side in LTR, right side in RTL
23
+ * - `end`: Right side in LTR, left side in RTL
24
+ * @default 'start'
25
+ */
26
+ origin: 'start' as 'start' | 'end',
27
+ /**
28
+ * The unique ID for the panel element. If not provided, a unique ID will be generated.
29
+ * This ID is used for the `aria-controls` attribute on the toggle button.
30
+ */
31
+ panelId: '',
32
+ /**
33
+ * The unique ID for the panel's label element. If not provided, a unique ID will be generated.
34
+ * This ID is used for the `aria-labelledby` attribute on both the panel and toggle button.
35
+ */
36
+ labelId: '',
37
+ /**
38
+ * Callback fired when the SidePanel's transition state changes.
39
+ * Use this to react to state changes including animation states.
40
+ * @param state The new transition state
41
+ */
42
+ onStateTransition(state: SidePanelTransitionStates) {
43
+ // no-op by default
44
+ },
45
+ },
46
+ })(config => {
47
+ const panelId = useUniqueId(config.panelId);
48
+ const labelId = useUniqueId(config.labelId);
49
+ const [transitionState, setTransitionStateInternal] = React.useState<SidePanelTransitionStates>(
50
+ config.initialTransitionState
51
+ );
52
+
53
+ // Wrap setTransitionState to call the onStateTransition callback
54
+ const setTransitionState = React.useCallback(
55
+ (newState: SidePanelTransitionStates) => {
56
+ setTransitionStateInternal(newState);
57
+ config.onStateTransition(newState);
58
+ },
59
+ [config]
60
+ );
61
+
62
+ const state = {
63
+ ...config,
64
+ /**
65
+ * The unique ID for the panel element. Used for `aria-controls` on the toggle button.
66
+ */
67
+ panelId,
68
+ /**
69
+ * The unique ID for the panel's label element. Used for `aria-labelledby` on the panel
70
+ * and toggle button to provide an accessible name.
71
+ */
72
+ labelId,
73
+ /**
74
+ * The current transition state of the SidePanel. This tracks both the expanded/collapsed
75
+ * state and the animation states (expanding/collapsing).
76
+ */
77
+ transitionState,
78
+ };
79
+
80
+ const events = {
81
+ /**
82
+ * Expand the SidePanel. This sets the state directly to `expanded` without animation.
83
+ * For animated expansion, use the toggle button which triggers `setExpandingState`.
84
+ */
85
+ expand() {
86
+ setTransitionState('expanded');
87
+ },
88
+
89
+ /**
90
+ * Collapse the SidePanel. This sets the state directly to `collapsed` without animation.
91
+ * For animated collapse, use the toggle button which triggers `setCollapsingState`.
92
+ */
93
+ collapse() {
94
+ setTransitionState('collapsed');
95
+ },
96
+
97
+ /**
98
+ * Handler for the CSS transition end event. This should be called when the width
99
+ * transition completes to finalize the state from `expanding` to `expanded` or
100
+ * from `collapsing` to `collapsed`.
101
+ */
102
+ handleAnimationEnd(event: React.TransitionEvent<HTMLDivElement>) {
103
+ if (event.propertyName === 'width') {
104
+ if (transitionState === 'expanding') {
105
+ setTransitionState('expanded');
106
+ } else if (transitionState === 'collapsing') {
107
+ setTransitionState('collapsed');
108
+ }
109
+ }
110
+ return event;
111
+ },
112
+
113
+ /**
114
+ * Triggers the start of a transition animation. This toggles between expanding
115
+ * and collapsing states based on the current state.
116
+ */
117
+ handleAnimationStart() {
118
+ if (transitionState === 'collapsed' || transitionState === 'collapsing') {
119
+ setTransitionState('expanding');
120
+ } else if (transitionState === 'expanded' || transitionState === 'expanding') {
121
+ setTransitionState('collapsing');
122
+ }
123
+ return undefined;
124
+ },
125
+ };
126
+
127
+ return {state, events};
128
+ });
@@ -0,0 +1,6 @@
1
+ {
2
+ "main": "../dist/commonjs/side-panel",
3
+ "module": "../dist/es6/side-panel",
4
+ "sideEffects": false,
5
+ "types": "../dist/es6/side-panel"
6
+ }