@crystallize/design-system 1.3.1 → 1.3.2

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 (146) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/dist/index.css +1813 -0
  3. package/dist/index.d.ts +345 -2
  4. package/dist/index.js +2631 -5
  5. package/dist/index.mjs +2574 -0
  6. package/package.json +90 -78
  7. package/readme.md +9 -0
  8. package/src/Tokens.stories.tsx +18 -0
  9. package/src/action-menu/ActionMenu.stories.tsx +25 -0
  10. package/src/action-menu/action-item.tsx +16 -0
  11. package/src/action-menu/action-menu.css +38 -0
  12. package/src/action-menu/action-menu.tsx +25 -0
  13. package/src/action-menu/index.tsx +3 -0
  14. package/src/avatar/Avatar.stories.tsx +20 -0
  15. package/src/avatar/avatar.css +23 -0
  16. package/src/avatar/avatar.tsx +34 -0
  17. package/src/avatar/get-initials.ts +5 -0
  18. package/src/avatar/index.ts +1 -0
  19. package/src/button/Button.stories.tsx +105 -0
  20. package/src/button/button.css +116 -0
  21. package/src/button/button.tsx +136 -0
  22. package/src/button/index.ts +3 -0
  23. package/src/card/card.css +7 -0
  24. package/src/card/card.stories.tsx +24 -0
  25. package/src/card/card.tsx +27 -0
  26. package/src/card/index.ts +3 -0
  27. package/src/checkbox/checkbox.css +30 -0
  28. package/src/checkbox/checkbox.stories.tsx +62 -0
  29. package/src/checkbox/checkbox.test.tsx +16 -0
  30. package/src/checkbox/checkbox.tsx +28 -0
  31. package/src/checkbox/index.ts +1 -0
  32. package/src/colors/Colors.stories.tsx +127 -0
  33. package/src/colors/color-defaults.json +15 -0
  34. package/src/colors/color-pairing.json +12 -0
  35. package/src/colors/colors.json +158 -0
  36. package/src/colors/index.ts +1 -0
  37. package/src/colors/old-to-new.txt +19 -0
  38. package/src/colors/types.ts +29 -0
  39. package/src/dialog/Dialog.stories.tsx +168 -0
  40. package/src/dialog/Dialog.test.tsx +25 -0
  41. package/src/dialog/config.tsx +139 -0
  42. package/src/dialog/confirm-dialog.tsx +70 -0
  43. package/src/dialog/destroyFns.ts +1 -0
  44. package/src/dialog/dialog.css +27 -0
  45. package/src/dialog/dialog.tsx +94 -0
  46. package/src/dialog/index.tsx +40 -0
  47. package/src/dialog/types.ts +70 -0
  48. package/src/dropdown-menu/DropdownMenu.stories.tsx +38 -0
  49. package/src/dropdown-menu/dropdown-menu-item.tsx +15 -0
  50. package/src/dropdown-menu/dropdown-menu-label.tsx +10 -0
  51. package/src/dropdown-menu/dropdown-menu-root.tsx +33 -0
  52. package/src/dropdown-menu/dropdown-menu.css +20 -0
  53. package/src/dropdown-menu/index.ts +11 -0
  54. package/src/icon-button/IconButton.stories.tsx +45 -0
  55. package/src/icon-button/icon-button.css +48 -0
  56. package/src/icon-button/icon-button.tsx +39 -0
  57. package/src/icon-button/index.ts +3 -0
  58. package/src/iconography/Icon.stories.tsx +47 -0
  59. package/src/iconography/add.tsx +30 -0
  60. package/src/iconography/arrow.tsx +15 -0
  61. package/src/iconography/atom.tsx +59 -0
  62. package/src/iconography/cancel.tsx +26 -0
  63. package/src/iconography/catalogue.tsx +26 -0
  64. package/src/iconography/copy.tsx +24 -0
  65. package/src/iconography/crystal.tsx +93 -0
  66. package/src/iconography/customers.tsx +38 -0
  67. package/src/iconography/edit.tsx +30 -0
  68. package/src/iconography/error.tsx +40 -0
  69. package/src/iconography/fulfilment.tsx +58 -0
  70. package/src/iconography/glasses.tsx +62 -0
  71. package/src/iconography/graphQL.tsx +90 -0
  72. package/src/iconography/grid.tsx +84 -0
  73. package/src/iconography/hooks.tsx +26 -0
  74. package/src/iconography/image.tsx +47 -0
  75. package/src/iconography/index.ts +63 -0
  76. package/src/iconography/info.tsx +41 -0
  77. package/src/iconography/key.tsx +19 -0
  78. package/src/iconography/language.tsx +38 -0
  79. package/src/iconography/nail-polish.tsx +84 -0
  80. package/src/iconography/order.tsx +38 -0
  81. package/src/iconography/particle.tsx +88 -0
  82. package/src/iconography/percentage.tsx +44 -0
  83. package/src/iconography/price-tag.tsx +40 -0
  84. package/src/iconography/shapes.tsx +48 -0
  85. package/src/iconography/subscription.tsx +34 -0
  86. package/src/iconography/topics.tsx +58 -0
  87. package/src/iconography/triangle.tsx +27 -0
  88. package/src/iconography/usage.tsx +34 -0
  89. package/src/iconography/users.tsx +44 -0
  90. package/src/iconography/warning.tsx +51 -0
  91. package/src/index.css +14 -0
  92. package/src/index.ts +33 -0
  93. package/src/inline-radio/index.ts +1 -0
  94. package/src/inline-radio/inline-radio.css +36 -0
  95. package/src/inline-radio/inline-radio.stories.tsx +81 -0
  96. package/src/inline-radio/inline-radio.tsx +41 -0
  97. package/src/input/Input.stories.tsx +26 -0
  98. package/src/input/index.ts +1 -0
  99. package/src/input/input.css +7 -0
  100. package/src/input/input.tsx +20 -0
  101. package/src/input-with-label/InputWithLabel.stories.tsx +98 -0
  102. package/src/input-with-label/index.ts +3 -0
  103. package/src/input-with-label/input-with-label.css +35 -0
  104. package/src/input-with-label/input-with-label.tsx +59 -0
  105. package/src/label/index.ts +1 -0
  106. package/src/label/label.css +3 -0
  107. package/src/label/label.stories.tsx +19 -0
  108. package/src/label/label.tsx +13 -0
  109. package/src/progress/Progress.stories.tsx +26 -0
  110. package/src/progress/index.ts +1 -0
  111. package/src/progress/progress.css +7 -0
  112. package/src/progress/progress.tsx +17 -0
  113. package/src/radio/index.ts +1 -0
  114. package/src/radio/radio.css +20 -0
  115. package/src/radio/radio.stories.tsx +142 -0
  116. package/src/radio/radio.tsx +19 -0
  117. package/src/select/index.ts +1 -0
  118. package/src/select/select-item.tsx +18 -0
  119. package/src/select/select-root.tsx +50 -0
  120. package/src/select/select.css +44 -0
  121. package/src/select/select.stories.tsx +74 -0
  122. package/src/select/select.ts +9 -0
  123. package/src/slider/Slider.stories.tsx +54 -0
  124. package/src/slider/index.ts +1 -0
  125. package/src/slider/slider.css +27 -0
  126. package/src/slider/slider.tsx +20 -0
  127. package/src/spinner/Spinner.stories.tsx +19 -0
  128. package/src/spinner/index.tsx +48 -0
  129. package/src/spinner/spinner.css +11 -0
  130. package/src/tag/Tag.stories.tsx +32 -0
  131. package/src/tag/index.ts +1 -0
  132. package/src/tag/tag.css +7 -0
  133. package/src/tag/tag.tsx +27 -0
  134. package/src/vite-env.d.ts +1 -0
  135. package/tailwind.config.cjs +51 -0
  136. package/LICENSE +0 -21
  137. package/README.md +0 -35
  138. package/dist/components/Button.d.ts +0 -11
  139. package/dist/components/Typography.d.ts +0 -14
  140. package/dist/design-system.cjs.development.js +0 -164
  141. package/dist/design-system.cjs.development.js.map +0 -1
  142. package/dist/design-system.cjs.production.min.js +0 -2
  143. package/dist/design-system.cjs.production.min.js.map +0 -1
  144. package/dist/design-system.esm.js +0 -156
  145. package/dist/design-system.esm.js.map +0 -1
  146. package/dist/styles/theme.d.ts +0 -2
@@ -0,0 +1,29 @@
1
+ export type Color = {
2
+ 50: string;
3
+ 100: string;
4
+ 200: string;
5
+ 300: string;
6
+ 400: string;
7
+ 500: string;
8
+ 600: string;
9
+ 700: string;
10
+ 800: string;
11
+ 900: string;
12
+ };
13
+
14
+ export type ColorName =
15
+ | 'cyan'
16
+ | 'pink'
17
+ | 'gray'
18
+ | 'purple'
19
+ | 'green'
20
+ | 'orange'
21
+ | 's-red'
22
+ | 's-orange'
23
+ | 's-yellow'
24
+ | 's-green'
25
+ | 's-blue'
26
+ | 's-purple'
27
+ | 's-pink';
28
+
29
+ export type Colors = Record<ColorName, Color>;
@@ -0,0 +1,168 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { Dialog, showDialog, showWarning, showConfirm, showInfo, showError } from '.';
4
+ import { ActionMenu } from '../action-menu';
5
+ import { Button } from '../button';
6
+
7
+ const meta: Meta<typeof Dialog> = {
8
+ title: 'Components/Dialog',
9
+ component: Dialog,
10
+ argTypes: {},
11
+ };
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof Dialog>;
16
+
17
+ const Lorem = () => (
18
+ <p className="leading-6">
19
+ Lorem ipsum, dolor sit amet consectetur adipisicing elit. Reiciendis neque id, blanditiis exercitationem doloremque
20
+ quam ab minima architecto culpa.
21
+ </p>
22
+ );
23
+
24
+ export const Component: Story = {
25
+ render: () => (
26
+ <Dialog>
27
+ <Dialog.Trigger asChild>
28
+ <Button>Open dialog</Button>
29
+ </Dialog.Trigger>
30
+ <Dialog.Content>
31
+ <Dialog.Title>This is a normal Dialog</Dialog.Title>
32
+ <Dialog.Description>That is described in a declarative way</Dialog.Description>
33
+ <div className="flex items-center justify-between">
34
+ Here will go the main content
35
+ <ActionMenu>
36
+ <ActionMenu.Item onSelect={() => console.warn('Download')}>Download</ActionMenu.Item>
37
+ <ActionMenu.Item className="danger" onSelect={() => console.warn('Delete')}>
38
+ Delete
39
+ </ActionMenu.Item>
40
+ </ActionMenu>
41
+ </div>
42
+ </Dialog.Content>
43
+ </Dialog>
44
+ ),
45
+ };
46
+
47
+ export const ComponentWithDangerAction: Story = {
48
+ name: 'With danger action',
49
+ render: () => (
50
+ <Dialog>
51
+ <Dialog.Trigger asChild>
52
+ <Button>Open dialog</Button>
53
+ </Dialog.Trigger>
54
+ <Dialog.Content>
55
+ <Dialog.Title>A Dialog</Dialog.Title>
56
+ <div>
57
+ <Dialog.Description>
58
+ <Lorem />
59
+ </Dialog.Description>
60
+
61
+ <div className="mt-8 flex justify-end gap-4">
62
+ <Button>Cancel</Button>
63
+ <Button intent="danger">Delete</Button>
64
+ </div>
65
+ </div>
66
+ </Dialog.Content>
67
+ </Dialog>
68
+ ),
69
+ };
70
+
71
+ export const ShowConfirm: Story = {
72
+ name: 'Show confirm',
73
+ render: () => {
74
+ const handleClick = () => {
75
+ showConfirm({
76
+ title: 'We need your confirmation',
77
+ description: 'In order to proceed to you account we need your confirmation',
78
+ content: (
79
+ <p className="my-6">
80
+ We really like cookies and our cookies is what allow us to provide you with an awesome user experience. Do
81
+ you allow us to set some cookies for you?
82
+ </p>
83
+ ),
84
+ okText: 'Yes sure',
85
+ cancelText: `I don't really like cookies`,
86
+ onCancel() {
87
+ console.warn('you canceled');
88
+ },
89
+ onOk() {
90
+ console.warn('you confirmed');
91
+ },
92
+ });
93
+ };
94
+
95
+ return <Button onClick={handleClick}>showConfirm</Button>;
96
+ },
97
+ };
98
+
99
+ export const ShowWarning: Story = {
100
+ name: 'Show warning',
101
+ render: () => {
102
+ const handleClick = () => {
103
+ showWarning({
104
+ title: 'A warning',
105
+ description: 'This is a warning dialog',
106
+ content: <Lorem />,
107
+ okText: `That's OK`,
108
+ onOk() {
109
+ console.warn('ok');
110
+ },
111
+ });
112
+ };
113
+
114
+ return <Button onClick={handleClick}>showWarning</Button>;
115
+ },
116
+ };
117
+
118
+ export const ShowError: Story = {
119
+ name: 'Show error',
120
+ render: () => {
121
+ const handleClick = () => {
122
+ showError({
123
+ title: 'Error',
124
+ description: 'This is an error dialog',
125
+ content: <Lorem />,
126
+ okText: `That's not good`,
127
+ onOk() {
128
+ console.warn('ok');
129
+ },
130
+ });
131
+ };
132
+
133
+ return <Button onClick={handleClick}>showError</Button>;
134
+ },
135
+ };
136
+
137
+ export const ShowInfo: Story = {
138
+ name: 'Show info',
139
+ render: () => {
140
+ const handleClick = () => {
141
+ showInfo({
142
+ title: 'Information',
143
+ description: 'This is an informative dialog',
144
+ content: <Lorem />,
145
+ okText: `I'm fine with that`,
146
+ onOk() {
147
+ console.warn('ok');
148
+ },
149
+ });
150
+ };
151
+
152
+ return <Button onClick={handleClick}>showInfo</Button>;
153
+ },
154
+ };
155
+
156
+ export const ShowDialog: Story = {
157
+ name: 'Show dialog',
158
+ render: () => {
159
+ const handleClick = () => {
160
+ showDialog({
161
+ title: 'Just to let you know',
162
+ content: <Lorem />,
163
+ });
164
+ };
165
+
166
+ return <Button onClick={handleClick}>showDialog</Button>;
167
+ },
168
+ };
@@ -0,0 +1,25 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+
3
+ import { Dialog } from '.';
4
+ import { Button } from '../button';
5
+
6
+ describe('testing the dialog', () => {
7
+ it('should open', () => {
8
+ render(
9
+ <Dialog>
10
+ <Dialog.Trigger asChild>
11
+ <Button>Open dialog</Button>
12
+ </Dialog.Trigger>
13
+ <Dialog.Content>
14
+ <Dialog.Title>This is a normal dialog</Dialog.Title>
15
+ <Dialog.Description>That is described in a declarative way</Dialog.Description>
16
+ <div className="flex items-center justify-between">Hello world!</div>
17
+ </Dialog.Content>
18
+ </Dialog>,
19
+ );
20
+
21
+ fireEvent.click(screen.getByText('Open dialog'));
22
+
23
+ expect(screen.getByText('This is a normal dialog')).toBeVisible();
24
+ });
25
+ });
@@ -0,0 +1,139 @@
1
+ import { unmountComponentAtNode, render as DOMRender } from 'react-dom';
2
+ import { ConfirmDialog } from './confirm-dialog';
3
+
4
+ import { destroyFns } from './destroyFns';
5
+ import type { ConfigUpdate, DialogFuncProps } from './types';
6
+
7
+ export function confirm(config: DialogFuncProps) {
8
+ const container = document.createDocumentFragment();
9
+ let currentConfig = { ...config, close, open: true };
10
+ let timeoutId: NodeJS.Timeout;
11
+
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ function close(...args: any[]) {
14
+ currentConfig = {
15
+ ...currentConfig,
16
+ open: false,
17
+ afterClose: () => {
18
+ if (typeof config.afterClose === 'function') {
19
+ config.afterClose();
20
+ }
21
+
22
+ destroy.apply(this, args);
23
+ },
24
+ };
25
+
26
+ render(currentConfig);
27
+ }
28
+
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ function destroy(...args: any[]) {
31
+ const triggerCancel = args.some(param => param && param.triggerCancel);
32
+
33
+ if (config.onCancel && triggerCancel) {
34
+ config.onCancel(() => {}, ...args.slice(1));
35
+ }
36
+
37
+ for (let i = 0; i < destroyFns.length; i++) {
38
+ const fn = destroyFns[i];
39
+
40
+ if (fn === close) {
41
+ destroyFns.splice(i, 1);
42
+ break;
43
+ }
44
+ }
45
+
46
+ unmountComponentAtNode(container);
47
+ }
48
+
49
+ function render({ okText, cancelText, ...delegated }: any) {
50
+ clearTimeout(timeoutId);
51
+
52
+ timeoutId = setTimeout(() => {
53
+ DOMRender(<ConfirmDialog {...delegated} okText={okText} cancelText={cancelText} />, container);
54
+ });
55
+ }
56
+
57
+ function update(configUpdate: ConfigUpdate) {
58
+ if (typeof configUpdate === 'function') {
59
+ currentConfig = configUpdate(currentConfig);
60
+ } else {
61
+ currentConfig = {
62
+ ...currentConfig,
63
+ ...configUpdate,
64
+ };
65
+ }
66
+
67
+ render(currentConfig);
68
+ }
69
+
70
+ render(currentConfig);
71
+
72
+ destroyFns.push(close);
73
+
74
+ return {
75
+ destroy: close,
76
+ update,
77
+ };
78
+ }
79
+
80
+ const dumbFn = (event: Event) => {
81
+ event.preventDefault();
82
+ };
83
+
84
+ export function withDialog(delegated: DialogFuncProps): DialogFuncProps {
85
+ return {
86
+ open: true,
87
+ displayCancel: true,
88
+ displayOk: true,
89
+ ...delegated,
90
+ };
91
+ }
92
+
93
+ export function withWarning(delegated: DialogFuncProps): DialogFuncProps {
94
+ return {
95
+ open: true,
96
+ displayCancel: false,
97
+ displayOk: true,
98
+ type: 'warning',
99
+ ...delegated,
100
+ onInteractOutside: dumbFn,
101
+ onPointerDownOutside: dumbFn,
102
+ };
103
+ }
104
+
105
+ export function withError(delegated: DialogFuncProps): DialogFuncProps {
106
+ return {
107
+ open: true,
108
+ displayOk: true,
109
+ displayCancel: false,
110
+ type: 'error',
111
+ ...delegated,
112
+ onInteractOutside: dumbFn,
113
+ onPointerDownOutside: dumbFn,
114
+ };
115
+ }
116
+
117
+ export function withInfo(delegated: DialogFuncProps): DialogFuncProps {
118
+ return {
119
+ open: true,
120
+ displayOk: true,
121
+ displayCancel: false,
122
+ type: 'info',
123
+ ...delegated,
124
+ onInteractOutside: dumbFn,
125
+ onPointerDownOutside: dumbFn,
126
+ };
127
+ }
128
+
129
+ export function withConfirm(delegated: DialogFuncProps): DialogFuncProps {
130
+ return {
131
+ open: true,
132
+ displayOk: true,
133
+ displayCancel: true,
134
+ type: 'info',
135
+ ...delegated,
136
+ onInteractOutside: dumbFn,
137
+ onPointerDownOutside: dumbFn,
138
+ };
139
+ }
@@ -0,0 +1,70 @@
1
+ import { Dialog } from '.';
2
+ import { Button } from '../button';
3
+ import { DialogRoot } from './dialog';
4
+ import type { ConfirmDialogProps } from './types';
5
+
6
+ export function ConfirmDialog({
7
+ open,
8
+ close,
9
+ title,
10
+ description,
11
+ content,
12
+ okCancel,
13
+ displayCancel,
14
+ displayOk,
15
+ okText = 'OK',
16
+ okButtonIntent = 'default',
17
+ onOk,
18
+ onCancel,
19
+ cancelText = 'Cancel',
20
+ onEscapeKeyDown,
21
+ onInteractOutside,
22
+ onPointerDownOutside,
23
+ type,
24
+ closable,
25
+ }: ConfirmDialogProps) {
26
+ const cancelButton = (okCancel || displayCancel) && (
27
+ <Button
28
+ onClick={() => {
29
+ onCancel?.();
30
+ close();
31
+ }}
32
+ >
33
+ {cancelText}
34
+ </Button>
35
+ );
36
+
37
+ const okButton = displayOk && (
38
+ <Button
39
+ intent={okButtonIntent}
40
+ onClick={() => {
41
+ onOk?.();
42
+ close();
43
+ }}
44
+ >
45
+ {okText}
46
+ </Button>
47
+ );
48
+
49
+ return (
50
+ <DialogRoot open={open} onOpenChange={() => close()}>
51
+ <Dialog.Content
52
+ onEscapeKeyDown={onEscapeKeyDown}
53
+ onInteractOutside={onInteractOutside}
54
+ onPointerDownOutside={onPointerDownOutside}
55
+ type={type}
56
+ closable={closable}
57
+ >
58
+ {title && <Dialog.Title>{title}</Dialog.Title>}
59
+ {description && <Dialog.Description>{description}</Dialog.Description>}
60
+ {content}
61
+ {(displayOk || okCancel || displayCancel) && (
62
+ <div className="mt-4 flex items-center justify-end gap-4">
63
+ {cancelButton}
64
+ {okButton}
65
+ </div>
66
+ )}
67
+ </Dialog.Content>
68
+ </DialogRoot>
69
+ );
70
+ }
@@ -0,0 +1 @@
1
+ export const destroyFns: Array<() => void> = [];
@@ -0,0 +1,27 @@
1
+ .c-dialog {
2
+ @apply fixed top-1/2 left-1/2 z-20 w-auto min-w-[25%] max-w-[800px] rounded-lg bg-elevate p-14 leading-6 text-gray-500-400 shadow;
3
+ transform: translate(-50%, -50%);
4
+ &-overlay {
5
+ @apply fixed inset-0 z-10 bg-overlay;
6
+ }
7
+
8
+ &-icon {
9
+ @apply my-1 shrink-0;
10
+ }
11
+
12
+ &-title {
13
+ @apply m-0 font-serif text-xl font-bold text-gray;
14
+ }
15
+
16
+ &-description {
17
+ @apply mt-1 mb-5 font-medium;
18
+ }
19
+
20
+ &-close-button {
21
+ @apply absolute top-0 right-0 inline-flex h-12 w-12 items-center justify-center rounded-none rounded-tr-lg border !bg-transparent !p-0 !drop-shadow-none hover:!bg-gray-50-900 focus:!bg-gray-50-900;
22
+ }
23
+
24
+ &-with-icon {
25
+ @apply flex items-start gap-6 pl-6;
26
+ }
27
+ }
@@ -0,0 +1,94 @@
1
+ import type { ReactNode, RefAttributes } from 'react';
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
+ import { cva, cx, VariantProps } from 'class-variance-authority';
4
+
5
+ import { Button } from '../button';
6
+ import { Icon } from '../iconography';
7
+ import type { DialogFuncProps } from './types';
8
+
9
+ import './dialog.css';
10
+
11
+ const IconMap = {
12
+ error: Icon.Error,
13
+ info: Icon.Info,
14
+ warning: Icon.Warning,
15
+ };
16
+
17
+ type DialogContentStylesProps = VariantProps<typeof dialogContentStyles>;
18
+ const dialogContentStyles = cva('c-dialog', {
19
+ variants: {
20
+ withIcon: {
21
+ true: 'c-dialog-with-icon',
22
+ },
23
+ },
24
+ });
25
+
26
+ type DialogContentProps = DialogContentStylesProps & {
27
+ children: ReactNode;
28
+ } & Pick<
29
+ DialogFuncProps,
30
+ 'onEscapeKeyDown' | 'onInteractOutside' | 'onPointerDownOutside' | 'closable' | 'type' | 'className'
31
+ > &
32
+ DialogPrimitive.DialogContentProps &
33
+ Pick<DialogPrimitive.PortalProps, 'container'>;
34
+
35
+ function DialogContent({ children, closable = true, type, className, container, ...delegated }: DialogContentProps) {
36
+ const withIcon = typeof type !== 'undefined';
37
+
38
+ const IconComponent = type && IconMap[type];
39
+
40
+ return (
41
+ <DialogPrimitive.Portal container={container}>
42
+ <DialogPrimitive.Overlay className="c-dialog-overlay" />
43
+ <DialogPrimitive.Content className={dialogContentStyles({ withIcon, class: className })} {...delegated}>
44
+ {IconComponent && (
45
+ <div className="flex h-[44px] w-[44px] min-w-[44px] items-center justify-center rounded-lg bg-gray-50-900 p-[5px]">
46
+ <IconComponent className="c-dialog-icon" width={34} height={34} />
47
+ </div>
48
+ )}
49
+ {closable && (
50
+ <DialogClose asChild>
51
+ <Button className="c-dialog-close-button">
52
+ <Icon.Cancel color="density" aria-label="Close" height={16} width={16} />
53
+ </Button>
54
+ </DialogClose>
55
+ )}
56
+ <div>{children}</div>
57
+ </DialogPrimitive.Content>
58
+ </DialogPrimitive.Portal>
59
+ );
60
+ }
61
+
62
+ type DialogTitleProps = JSX.IntrinsicAttributes & DialogPrimitive.DialogTitleProps & RefAttributes<HTMLHeadingElement>;
63
+
64
+ function DialogTitle({ className, ...delegated }: DialogTitleProps) {
65
+ return <DialogPrimitive.Title className={cx('c-dialog-title', className)} {...delegated} />;
66
+ }
67
+
68
+ type DialogDescriptionProps = JSX.IntrinsicAttributes &
69
+ DialogPrimitive.DialogDescriptionProps &
70
+ RefAttributes<HTMLParagraphElement>;
71
+
72
+ function DialogDescription(delegated: DialogDescriptionProps) {
73
+ return <DialogPrimitive.Description className="c-dialog-description" {...delegated} />;
74
+ }
75
+
76
+ const DialogTrigger = DialogPrimitive.Trigger;
77
+
78
+ const DialogClose = DialogPrimitive.Close;
79
+
80
+ export const DialogRoot = DialogPrimitive.Root;
81
+
82
+ type DialogBaseProps = React.ComponentProps<typeof DialogRoot> & {
83
+ children: ReactNode;
84
+ };
85
+
86
+ export function DialogBase({ children, ...delegated }: DialogBaseProps) {
87
+ return <DialogRoot {...delegated}>{children}</DialogRoot>;
88
+ }
89
+
90
+ DialogBase.Title = DialogTitle;
91
+ DialogBase.Trigger = DialogTrigger;
92
+ DialogBase.Description = DialogDescription;
93
+ DialogBase.Content = DialogContent;
94
+ DialogBase.Overlay = DialogPrimitive.Overlay;
@@ -0,0 +1,40 @@
1
+ import { destroyFns } from './destroyFns';
2
+ import { DialogBase } from './dialog';
3
+ import type { DialogFuncProps } from './types';
4
+ import { confirm, withWarning, withConfirm, withDialog, withError, withInfo } from './config';
5
+
6
+ type DialogType = typeof DialogBase & DialogFuncProps;
7
+
8
+ const Dialog = DialogBase as DialogType;
9
+
10
+ function showDialog(delegated: DialogFuncProps) {
11
+ return confirm(withDialog(delegated));
12
+ }
13
+
14
+ function showWarning(delegated: DialogFuncProps) {
15
+ return confirm(withWarning(delegated));
16
+ }
17
+
18
+ function showConfirm(delegated: DialogFuncProps) {
19
+ return confirm(withConfirm(delegated));
20
+ }
21
+
22
+ function showError(delegated: DialogFuncProps) {
23
+ return confirm(withError(delegated));
24
+ }
25
+
26
+ function showInfo(delegated: DialogFuncProps) {
27
+ return confirm(withInfo(delegated));
28
+ }
29
+
30
+ function destroyAll() {
31
+ while (destroyFns.length) {
32
+ const close = destroyFns.pop();
33
+
34
+ if (close) {
35
+ close();
36
+ }
37
+ }
38
+ }
39
+
40
+ export { Dialog, destroyAll, showWarning, showConfirm, showDialog, showError, showInfo };
@@ -0,0 +1,70 @@
1
+ import type { ReactNode, ComponentProps } from 'react';
2
+
3
+ import type { Button } from '../button';
4
+
5
+ export type DialogFuncProps = {
6
+ afterClose?: () => void;
7
+ /**
8
+ * Text that should be displayed in the cancel button
9
+ */
10
+ cancelText?: ReactNode;
11
+ className?: string;
12
+ closable?: boolean;
13
+ content?: ReactNode;
14
+ description?: ReactNode;
15
+ /**
16
+ * Flag that controls if the cancel button should be included in the dialog or not
17
+ */
18
+ displayCancel?: boolean;
19
+ /**
20
+ * Flag that controls if the ok button should be included in the dialog or not
21
+ */
22
+ displayOk?: boolean;
23
+ /**
24
+ * @deprecated - Use displayCancel instead
25
+ *
26
+ * Flag that controls if the cancel button should be included in the dialog or not
27
+ */
28
+ okCancel?: boolean;
29
+ /**
30
+ * Text that should be displayed in the ok button
31
+ */
32
+ okText?: ReactNode;
33
+ okButtonIntent?: ComponentProps<typeof Button>['intent'];
34
+ /**
35
+ * The callback that will be called once the user click the cancel button
36
+ * @param args
37
+ * @returns void
38
+ */
39
+ onCancel?: (...args: unknown[]) => void;
40
+ onEscapeKeyDown?: (event: Event) => void;
41
+ onInteractOutside?: (event: Event) => void;
42
+ /**
43
+ * The callback that will be called once the user click the ok button
44
+ * @param args
45
+ * @returns void
46
+ */
47
+ onOk?: (...args: unknown[]) => void;
48
+ onPointerDownOutside?: (event: Event) => void;
49
+ open?: boolean;
50
+ prefixCls?: string;
51
+ title?: ReactNode;
52
+ type?: 'info' | 'error' | 'warning';
53
+ };
54
+
55
+ export type ConfigUpdate = DialogFuncProps | ((prevConfig: DialogFuncProps) => DialogFuncProps);
56
+
57
+ export type DialogFunc = (props: DialogFuncProps) => {
58
+ destroy: () => void;
59
+ update: (configUpdate: ConfigUpdate) => void;
60
+ };
61
+
62
+ export type ModalStaticFunctions = Record<NonNullable<DialogFuncProps['type']>, DialogFunc>;
63
+
64
+ export interface ConfirmDialogProps extends DialogFuncProps {
65
+ afterClose?: () => void;
66
+ close: (...args: unknown[]) => void;
67
+ autoFocusButton?: null | 'ok' | 'cancel';
68
+ rootPrefixCls: string;
69
+ iconPrefixCls?: string;
70
+ }