@scalepad/ui 0.1.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.
- package/.ai/rules/date-handling.md +39 -0
- package/.ai/rules/figma-design-system.md +372 -0
- package/.ai/rules/figma-lm-design-system-keys.md +680 -0
- package/.ai/rules/file-extensions.md +13 -0
- package/.ai/rules/modal-confirmation-mutation.md +56 -0
- package/.ai/rules/react-hooks.md +29 -0
- package/.ai/rules/styling.md +83 -0
- package/AGENTS.md +37 -0
- package/README.md +125 -0
- package/figma.config.json +9 -0
- package/package.json +127 -0
- package/scripts/install-ai-rules.mjs +136 -0
- package/src/ThemeProvider.tsx +57 -0
- package/src/charts.ts +32 -0
- package/src/components/ActionCard/ActionCard.css.ts +60 -0
- package/src/components/ActionCard/ActionCard.tsx +154 -0
- package/src/components/ActionCard/index.ts +2 -0
- package/src/components/Anchor/Anchor.tsx +47 -0
- package/src/components/Anchor/index.ts +2 -0
- package/src/components/AppliedFiltersManagerBar/AppliedFiltersManagerBar.tsx +105 -0
- package/src/components/AppliedFiltersManagerBar/FilterBadge.css.ts +23 -0
- package/src/components/AppliedFiltersManagerBar/FilterBadge.tsx +50 -0
- package/src/components/AppliedFiltersManagerBar/index.ts +5 -0
- package/src/components/Badge/Badge.css.ts +72 -0
- package/src/components/Badge/Badge.figma.tsx +43 -0
- package/src/components/Badge/Badge.tsx +159 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/BreadCrumb/BreadCrumb.tsx +62 -0
- package/src/components/BreadCrumb/index.ts +2 -0
- package/src/components/BulkActionBar/BulkActionBar.css.ts +26 -0
- package/src/components/BulkActionBar/BulkActionBar.tsx +164 -0
- package/src/components/BulkActionBar/index.ts +2 -0
- package/src/components/Button/Button.css.ts +272 -0
- package/src/components/Button/Button.figma.tsx +74 -0
- package/src/components/Button/Button.tsx +84 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/Charts/ChartTooltip.figma.tsx +33 -0
- package/src/components/Charts/ChartTooltip.tsx +101 -0
- package/src/components/Charts/MiniBarSparkline.tsx +75 -0
- package/src/components/Charts/StackedPatternBarChart.tsx +494 -0
- package/src/components/Charts/TrendAreaChart.css.ts +23 -0
- package/src/components/Charts/TrendAreaChart.tsx +210 -0
- package/src/components/Charts/index.ts +12 -0
- package/src/components/CodePanel/CodePanel.css.ts +113 -0
- package/src/components/CodePanel/CodePanel.tsx +121 -0
- package/src/components/CodePanel/index.ts +2 -0
- package/src/components/CommentComposer/CommentComposer.css.ts +60 -0
- package/src/components/CommentComposer/CommentComposer.tsx +181 -0
- package/src/components/CommentComposer/index.ts +2 -0
- package/src/components/ConfirmationModal/ConfirmationModal.tsx +149 -0
- package/src/components/ConfirmationModal/index.ts +2 -0
- package/src/components/ConfirmationTooltip/ConfirmationTooltip.tsx +132 -0
- package/src/components/ConfirmationTooltip/index.ts +2 -0
- package/src/components/DataDialog.figma.tsx +33 -0
- package/src/components/DataDialog.tsx +46 -0
- package/src/components/DataTable/DataTable.tsx +1042 -0
- package/src/components/DataTable/RowExpandToggle.tsx +105 -0
- package/src/components/DataTable/RowGroupHeader.tsx +190 -0
- package/src/components/DataTable/createActionsColumn.tsx +86 -0
- package/src/components/DataTable/index.ts +25 -0
- package/src/components/DatePicker/CustomRangePicker.tsx +59 -0
- package/src/components/DatePicker/DateInput.tsx +329 -0
- package/src/components/DatePicker/DateNavigator.tsx +486 -0
- package/src/components/DatePicker/DatePicker.tsx +242 -0
- package/src/components/DatePicker/MonthlyRangePicker.tsx +231 -0
- package/src/components/DatePicker/QuarterlyRangePicker.tsx +224 -0
- package/src/components/DatePicker/QuickPicksSidebar.tsx +242 -0
- package/src/components/DatePicker/YearlyRangePicker.tsx +171 -0
- package/src/components/DatePicker/index.ts +7 -0
- package/src/components/DatePicker/types.ts +12 -0
- package/src/components/DesignSystemPrimitives/FluidGrid.tsx +44 -0
- package/src/components/DesignSystemPrimitives/InteractivePrimitives.tsx +177 -0
- package/src/components/DesignSystemPrimitives/LayoutPrimitives.tsx +220 -0
- package/src/components/DesignSystemPrimitives/LayoutPrimitives.types.tsx +15 -0
- package/src/components/DesignSystemPrimitives/SurfacePrimitives.tsx +46 -0
- package/src/components/DesignSystemPrimitives/index.ts +55 -0
- package/src/components/Details/Details.css.ts +74 -0
- package/src/components/Details/Details.tsx +140 -0
- package/src/components/Details/index.ts +2 -0
- package/src/components/DownloadCard/DownloadCard.css.ts +22 -0
- package/src/components/DownloadCard/DownloadCard.tsx +63 -0
- package/src/components/DownloadCard/index.ts +2 -0
- package/src/components/Drawer/Drawer.css.ts +32 -0
- package/src/components/Drawer/Drawer.tsx +236 -0
- package/src/components/Drawer/hooks/useDetailDrawer.ts +61 -0
- package/src/components/Drawer/hooks/useDetailDrawerNavigation.ts +125 -0
- package/src/components/Drawer/hooks/useDetailDrawerNavigationContext.ts +66 -0
- package/src/components/EditableRichText/EditableRichText.css.ts +72 -0
- package/src/components/EditableRichText/EditableRichText.tsx +324 -0
- package/src/components/EditableRichText/index.ts +2 -0
- package/src/components/EditableSelect/EditableSelect.css.ts +62 -0
- package/src/components/EditableSelect/EditableSelect.tsx +224 -0
- package/src/components/EditableSelect/index.ts +2 -0
- package/src/components/EditableText/EditableText.tsx +377 -0
- package/src/components/EditableText/index.ts +2 -0
- package/src/components/EmptyState/EmptyState.figma.tsx +33 -0
- package/src/components/EmptyState/EmptyState.tsx +230 -0
- package/src/components/EmptyState/index.ts +2 -0
- package/src/components/ErrorBoundary.tsx +135 -0
- package/src/components/ErrorState/ErrorState.tsx +197 -0
- package/src/components/ErrorState/index.ts +2 -0
- package/src/components/FeatureCard.tsx +42 -0
- package/src/components/FilterMenu/FilterMenu.figma.tsx +30 -0
- package/src/components/FilterMenu/FilterMenu.tsx +198 -0
- package/src/components/FilterMenu/FilterSubMenuTypes/BooleanFilterSubmenu.tsx +46 -0
- package/src/components/FilterMenu/FilterSubMenuTypes/SearchableFilterSubmenu.tsx +239 -0
- package/src/components/FilterMenu/FilterSubMenuTypes/index.ts +8 -0
- package/src/components/FilterMenu/defaultFilterSchemas.ts +63 -0
- package/src/components/FilterMenu/helpers.ts +115 -0
- package/src/components/FilterMenu/index.ts +35 -0
- package/src/components/FilterMenu/types.ts +101 -0
- package/src/components/IconButton/IconButton.css.ts +272 -0
- package/src/components/IconButton/IconButton.figma.tsx +47 -0
- package/src/components/IconButton/IconButton.tsx +72 -0
- package/src/components/IconButton/README.md +230 -0
- package/src/components/IconButton/index.ts +2 -0
- package/src/components/InfiniteScrollSentinel.tsx +86 -0
- package/src/components/InfiniteScrollTrigger.tsx +78 -0
- package/src/components/InfoCard.figma.tsx +47 -0
- package/src/components/InfoCard.tsx +216 -0
- package/src/components/KbdHint/KbdHint.tsx +23 -0
- package/src/components/KbdHint/index.ts +2 -0
- package/src/components/LabeledField/LabeledField.tsx +21 -0
- package/src/components/LabeledField/index.ts +2 -0
- package/src/components/LookupSelect/LookupSelect.css.ts +149 -0
- package/src/components/LookupSelect/LookupSelect.tsx +325 -0
- package/src/components/LookupSelect/index.ts +2 -0
- package/src/components/Menu/Menu.css.ts +89 -0
- package/src/components/Menu/Menu.tsx +105 -0
- package/src/components/Menu/index.ts +2 -0
- package/src/components/MessageBox/MessageBox.tsx +168 -0
- package/src/components/MessageBox/index.ts +2 -0
- package/src/components/MetricDisplay/MetricDisplay.tsx +55 -0
- package/src/components/MetricDisplay/index.ts +1 -0
- package/src/components/MultiSelect/MultiSelect.tsx +278 -0
- package/src/components/MultiSelect/index.ts +2 -0
- package/src/components/Notifications/Notifications.tsx +12 -0
- package/src/components/Notifications/README.md +93 -0
- package/src/components/Notifications/index.ts +4 -0
- package/src/components/Notifications/showToast.tsx +100 -0
- package/src/components/PropertyRow/PropertyRow.tsx +96 -0
- package/src/components/PropertyRow/index.ts +2 -0
- package/src/components/RadioTile/RadioTile.tsx +253 -0
- package/src/components/RadioTile/index.ts +2 -0
- package/src/components/RichText/FormattingToolbar.css.ts +69 -0
- package/src/components/RichText/FormattingToolbar.tsx +112 -0
- package/src/components/RichText/RichTextInline.css.ts +54 -0
- package/src/components/RichText/RichTextInline.tsx +318 -0
- package/src/components/RichText/formattingCommands.ts +181 -0
- package/src/components/RichText/formattingTypes.ts +34 -0
- package/src/components/RichText/index.ts +49 -0
- package/src/components/RichText/richTextExtensions.ts +111 -0
- package/src/components/RichText/richTextHelpers.ts +65 -0
- package/src/components/RichText/richTextImage.ts +253 -0
- package/src/components/RichText/richTextImageHandlers.ts +244 -0
- package/src/components/RichText/richTextProse.css.ts +261 -0
- package/src/components/RichTextEditor/RichTextEditor.css.ts +82 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +204 -0
- package/src/components/RichTextEditor/index.ts +2 -0
- package/src/components/RichTextView/RichTextView.css.ts +11 -0
- package/src/components/RichTextView/RichTextView.tsx +114 -0
- package/src/components/RichTextView/index.ts +2 -0
- package/src/components/Schedule/Schedule.tsx +35 -0
- package/src/components/SchedulePicker/SchedulePicker.css.ts +42 -0
- package/src/components/SchedulePicker/SchedulePicker.tsx +130 -0
- package/src/components/SchedulePicker/index.ts +2 -0
- package/src/components/SearchableList/types.ts +30 -0
- package/src/components/SearchableSubMenu/SearchableSubMenu.css.ts +25 -0
- package/src/components/SearchableSubMenu/SearchableSubMenu.tsx +139 -0
- package/src/components/SearchableSubMenu/index.ts +2 -0
- package/src/components/Select/README.md +114 -0
- package/src/components/Select/Select.css.ts +110 -0
- package/src/components/Select/Select.tsx +133 -0
- package/src/components/Select/index.ts +2 -0
- package/src/components/SelectCreatable/SelectCreatable.css.ts +16 -0
- package/src/components/SelectCreatable/SelectCreatable.tsx +203 -0
- package/src/components/SelectCreatable/index.ts +2 -0
- package/src/components/SettingsCard/SettingsCard.tsx +98 -0
- package/src/components/SettingsCard/index.ts +2 -0
- package/src/components/Sidebar/Sidebar.css.ts +91 -0
- package/src/components/Sidebar/Sidebar.tsx +129 -0
- package/src/components/Sidebar/index.ts +5 -0
- package/src/components/SimpleList/SimpleList.css.ts +12 -0
- package/src/components/SimpleList/SimpleList.tsx +44 -0
- package/src/components/SimpleList/index.ts +2 -0
- package/src/components/SimpleTable/SimpleTable.tsx +296 -0
- package/src/components/SimpleTable/index.ts +2 -0
- package/src/components/SlashRichTextEditor/SelectionBubbleMenu.css.ts +62 -0
- package/src/components/SlashRichTextEditor/SelectionBubbleMenu.tsx +85 -0
- package/src/components/SlashRichTextEditor/SlashCommandMenu.css.ts +124 -0
- package/src/components/SlashRichTextEditor/SlashCommandMenu.tsx +168 -0
- package/src/components/SlashRichTextEditor/SlashRichTextEditor.css.ts +81 -0
- package/src/components/SlashRichTextEditor/SlashRichTextEditor.tsx +538 -0
- package/src/components/SlashRichTextEditor/SlashSuggestionExtension.ts +48 -0
- package/src/components/SlashRichTextEditor/index.ts +13 -0
- package/src/components/SlashRichTextEditor/types.ts +48 -0
- package/src/components/StatCard/StatCard.css.ts +70 -0
- package/src/components/StatCard/StatCard.tsx +201 -0
- package/src/components/StatCard/index.ts +1 -0
- package/src/components/StatusBadge/StatusBadge.tsx +70 -0
- package/src/components/StatusBadge/index.ts +2 -0
- package/src/components/StatusIndicator/StatusIndicator.tsx +67 -0
- package/src/components/StatusIndicator/index.ts +6 -0
- package/src/components/SubNavigation/SubNavigation.css.ts +72 -0
- package/src/components/SubNavigation/SubNavigation.tsx +104 -0
- package/src/components/SubNavigation/index.ts +2 -0
- package/src/components/SuspenseLoader.tsx +22 -0
- package/src/components/Table/SortableColumnHeader.tsx +99 -0
- package/src/components/Table/TableSkeletonRows.figma.tsx +22 -0
- package/src/components/Table/TableSkeletonRows.tsx +113 -0
- package/src/components/Table/index.ts +9 -0
- package/src/components/TableActionsMenu.tsx +58 -0
- package/src/components/TableCard.tsx +29 -0
- package/src/components/TableContainer/TableContainer.tsx +86 -0
- package/src/components/TableContainer/index.ts +2 -0
- package/src/components/TableControlBar/TableControlBar.tsx +156 -0
- package/src/components/TableControlBar/TableSelectionButton.tsx +57 -0
- package/src/components/TableControlBar/index.ts +13 -0
- package/src/components/TableControlBar/useTableControlBar.tsx +314 -0
- package/src/components/TableSelection/TableSelection.tsx +43 -0
- package/src/components/TableSelection/index.ts +5 -0
- package/src/components/Tabs/README.md +76 -0
- package/src/components/Tabs/Tabs.css.ts +54 -0
- package/src/components/Tabs/Tabs.figma.tsx +47 -0
- package/src/components/Tabs/Tabs.tsx +96 -0
- package/src/components/Tabs/index.ts +8 -0
- package/src/components/TextInput/README.md +98 -0
- package/src/components/TextInput/SearchTextInput.figma.tsx +22 -0
- package/src/components/TextInput/SearchTextInput.tsx +150 -0
- package/src/components/TextInput/TextInput.figma.tsx +44 -0
- package/src/components/TextInput/TextInput.tsx +42 -0
- package/src/components/TextInput/index.ts +4 -0
- package/src/components/ThemeSwitcher.figma.tsx +28 -0
- package/src/components/ThemeSwitcher.tsx +69 -0
- package/src/components/TrendBadge/TrendBadge.tsx +76 -0
- package/src/components/TrendBadge/index.ts +2 -0
- package/src/components/TruncatedText.tsx +115 -0
- package/src/components/Typography/Text.tsx +74 -0
- package/src/components/Typography/Title.tsx +100 -0
- package/src/components/Typography/index.ts +4 -0
- package/src/geist-fonts.ts +48 -0
- package/src/hooks/index.ts +31 -0
- package/src/hooks/useFilters.ts +152 -0
- package/src/hooks/useInfiniteScroll.ts +62 -0
- package/src/hooks/usePlatform.ts +33 -0
- package/src/hooks/useServerTable.ts +495 -0
- package/src/hooks/useTableSelection.ts +102 -0
- package/src/hooks/useTableSort.ts +259 -0
- package/src/index.ts +483 -0
- package/src/mantine.ts +25 -0
- package/src/theme/mantineVars.ts +12 -0
- package/src/theme/themeContract.css.ts +131 -0
- package/src/theme/themeVars.ts +31 -0
- package/src/theme.ts +168 -0
- package/src/tokens/color-types.ts +107 -0
- package/src/tokens/colors.ts +243 -0
- package/src/tokens/index.ts +14 -0
- package/src/tokens/radius.ts +17 -0
- package/src/tokens/semantic-colors.ts +224 -0
- package/src/tokens/semantic-tokens-css.ts +53 -0
- package/src/tokens/shadows.ts +11 -0
- package/src/tokens/spacing.ts +20 -0
- package/src/tokens/text-styles.ts +179 -0
- package/src/tokens/typography.ts +40 -0
- package/src/tokens/zIndex.ts +27 -0
- package/src/types/mantine-theme.d.ts +17 -0
- package/src/types/tanstack-table.d.ts +22 -0
- package/src/utils/avatar.ts +150 -0
- package/src/utils/chartHelpers.ts +53 -0
- package/src/utils/color-props.ts +77 -0
- package/src/utils/createDesignComponent.tsx +104 -0
- package/src/utils/nestFlatRows.ts +111 -0
- package/src/utils/withStaticComponents.ts +6 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Flex, Modal, type ModalProps } from '@mantine/core';
|
|
4
|
+
|
|
5
|
+
import { Button } from '../Button';
|
|
6
|
+
import { Text } from '../Typography';
|
|
7
|
+
|
|
8
|
+
export interface ConfirmationModalProps extends Omit<
|
|
9
|
+
ModalProps,
|
|
10
|
+
'children' | 'onClose'
|
|
11
|
+
> {
|
|
12
|
+
/**
|
|
13
|
+
* Modal title (displayed in header)
|
|
14
|
+
*/
|
|
15
|
+
title: string;
|
|
16
|
+
/**
|
|
17
|
+
* Modal description/message
|
|
18
|
+
*/
|
|
19
|
+
description: string | ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* Confirm button label
|
|
22
|
+
* @default "Confirm"
|
|
23
|
+
*/
|
|
24
|
+
confirmLabel?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Cancel button label
|
|
27
|
+
* @default "Cancel"
|
|
28
|
+
*/
|
|
29
|
+
cancelLabel?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Callback when confirm is clicked
|
|
32
|
+
*/
|
|
33
|
+
onConfirm: () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Callback when cancel is clicked or modal is closed (via X button or overlay click).
|
|
36
|
+
* This automatically maps to the modal's onClose handler.
|
|
37
|
+
*/
|
|
38
|
+
onCancel: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Variant of the confirmation dialog
|
|
41
|
+
* @default "default"
|
|
42
|
+
*/
|
|
43
|
+
variant?: 'default' | 'destructive';
|
|
44
|
+
/**
|
|
45
|
+
* Whether the confirm button is loading
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
confirmLoading?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Left section of the confirm button
|
|
51
|
+
*/
|
|
52
|
+
confirmButtonLeftSection?: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the confirm button is disabled
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
confirmDisabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* ConfirmationModal Component
|
|
62
|
+
*
|
|
63
|
+
* A reusable confirmation dialog for user actions requiring explicit confirmation.
|
|
64
|
+
* Supports both general confirmations (default variant) and critical/destructive actions (destructive variant).
|
|
65
|
+
* Follows Figma Dialog pattern with header, body, and footer.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* // Default variant for general confirmations
|
|
70
|
+
* <ConfirmationModal
|
|
71
|
+
* opened={opened}
|
|
72
|
+
* title="Update Agent"
|
|
73
|
+
* description="Update the agent on 3 devices to the latest version?"
|
|
74
|
+
* confirmLabel="Update Agent"
|
|
75
|
+
* onConfirm={handleUpdate}
|
|
76
|
+
* onCancel={close}
|
|
77
|
+
* />
|
|
78
|
+
*
|
|
79
|
+
* // Destructive variant for critical actions
|
|
80
|
+
* <ConfirmationModal
|
|
81
|
+
* opened={opened}
|
|
82
|
+
* title="Delete Device"
|
|
83
|
+
* description="This action cannot be undone."
|
|
84
|
+
* confirmLabel="Delete"
|
|
85
|
+
* onConfirm={handleDelete}
|
|
86
|
+
* onCancel={close}
|
|
87
|
+
* variant="destructive"
|
|
88
|
+
* />
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export function ConfirmationModal({
|
|
92
|
+
title,
|
|
93
|
+
description,
|
|
94
|
+
confirmLabel = 'Confirm',
|
|
95
|
+
cancelLabel = 'Cancel',
|
|
96
|
+
onConfirm,
|
|
97
|
+
onCancel,
|
|
98
|
+
variant = 'default',
|
|
99
|
+
confirmLoading = false,
|
|
100
|
+
confirmButtonLeftSection,
|
|
101
|
+
confirmDisabled = false,
|
|
102
|
+
...modalProps
|
|
103
|
+
}: ConfirmationModalProps) {
|
|
104
|
+
const isDestructive = variant === 'destructive';
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<Modal
|
|
108
|
+
{...modalProps}
|
|
109
|
+
title={title}
|
|
110
|
+
onClose={onCancel}
|
|
111
|
+
centered
|
|
112
|
+
padding="xl"
|
|
113
|
+
radius="xl"
|
|
114
|
+
size="md"
|
|
115
|
+
withCloseButton
|
|
116
|
+
>
|
|
117
|
+
<Flex direction="column" gap="xl">
|
|
118
|
+
{/* Description */}
|
|
119
|
+
{typeof description === 'string' ? (
|
|
120
|
+
<Text variant="caption1" c="text.subdued.default">
|
|
121
|
+
{description}
|
|
122
|
+
</Text>
|
|
123
|
+
) : (
|
|
124
|
+
description
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{/* Actions */}
|
|
128
|
+
<Flex gap="xs" justify="flex-end">
|
|
129
|
+
<Button
|
|
130
|
+
variant="outline"
|
|
131
|
+
onClick={onCancel}
|
|
132
|
+
disabled={confirmLoading}
|
|
133
|
+
>
|
|
134
|
+
{cancelLabel}
|
|
135
|
+
</Button>
|
|
136
|
+
<Button
|
|
137
|
+
variant={isDestructive ? 'destructive' : 'primary'}
|
|
138
|
+
onClick={onConfirm}
|
|
139
|
+
loading={confirmLoading}
|
|
140
|
+
disabled={confirmDisabled}
|
|
141
|
+
leftSection={confirmButtonLeftSection}
|
|
142
|
+
>
|
|
143
|
+
{confirmLabel}
|
|
144
|
+
</Button>
|
|
145
|
+
</Flex>
|
|
146
|
+
</Flex>
|
|
147
|
+
</Modal>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cloneElement,
|
|
3
|
+
useEffect,
|
|
4
|
+
useRef,
|
|
5
|
+
useState,
|
|
6
|
+
type MouseEvent,
|
|
7
|
+
type ReactElement,
|
|
8
|
+
} from 'react';
|
|
9
|
+
|
|
10
|
+
import { Tooltip, type TooltipProps } from '@mantine/core';
|
|
11
|
+
|
|
12
|
+
type SupportedChildProps = {
|
|
13
|
+
onClick?: (event: MouseEvent<HTMLElement>) => void;
|
|
14
|
+
'aria-label'?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export interface ConfirmationTooltipProps {
|
|
18
|
+
/**
|
|
19
|
+
* Interactive element that triggers confirmation.
|
|
20
|
+
*/
|
|
21
|
+
children: ReactElement<SupportedChildProps>;
|
|
22
|
+
/**
|
|
23
|
+
* Tooltip label shown while confirmed.
|
|
24
|
+
* @default 'Copied'
|
|
25
|
+
*/
|
|
26
|
+
label?: TooltipProps['label'];
|
|
27
|
+
/**
|
|
28
|
+
* Confirmation visibility duration in milliseconds.
|
|
29
|
+
* @default 1500
|
|
30
|
+
*/
|
|
31
|
+
durationMs?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Optional aria-label to apply while confirmation is visible.
|
|
34
|
+
*/
|
|
35
|
+
confirmedAriaLabel?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Tooltip position relative to the child.
|
|
38
|
+
* @default 'top'
|
|
39
|
+
*/
|
|
40
|
+
position?: TooltipProps['position'];
|
|
41
|
+
/**
|
|
42
|
+
* Whether to show a tooltip arrow.
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
withArrow?: TooltipProps['withArrow'];
|
|
46
|
+
/**
|
|
47
|
+
* Tooltip color token.
|
|
48
|
+
* @default 'dark'
|
|
49
|
+
*/
|
|
50
|
+
color?: TooltipProps['color'];
|
|
51
|
+
/**
|
|
52
|
+
* Whether tooltip should render inside a portal.
|
|
53
|
+
*/
|
|
54
|
+
withinPortal?: TooltipProps['withinPortal'];
|
|
55
|
+
/**
|
|
56
|
+
* Tooltip transition configuration.
|
|
57
|
+
*/
|
|
58
|
+
transitionProps?: TooltipProps['transitionProps'];
|
|
59
|
+
/**
|
|
60
|
+
* Disables the confirmation behavior.
|
|
61
|
+
* Child click still fires as normal.
|
|
62
|
+
* @default false
|
|
63
|
+
*/
|
|
64
|
+
disabled?: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Wraps any clickable child and shows a short-lived confirmation tooltip after click.
|
|
69
|
+
*/
|
|
70
|
+
export function ConfirmationTooltip({
|
|
71
|
+
children,
|
|
72
|
+
label = 'Copied',
|
|
73
|
+
durationMs = 1500,
|
|
74
|
+
confirmedAriaLabel,
|
|
75
|
+
position = 'top',
|
|
76
|
+
withArrow = false,
|
|
77
|
+
color = 'dark',
|
|
78
|
+
withinPortal,
|
|
79
|
+
transitionProps,
|
|
80
|
+
disabled = false,
|
|
81
|
+
}: ConfirmationTooltipProps) {
|
|
82
|
+
const [isConfirmed, setIsConfirmed] = useState(false);
|
|
83
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
84
|
+
|
|
85
|
+
const clearConfirmationTimeout = () => {
|
|
86
|
+
if (!timeoutRef.current) return;
|
|
87
|
+
clearTimeout(timeoutRef.current);
|
|
88
|
+
timeoutRef.current = null;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
useEffect(
|
|
92
|
+
() => () => {
|
|
93
|
+
clearConfirmationTimeout();
|
|
94
|
+
},
|
|
95
|
+
[],
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const handleClick = (event: MouseEvent<HTMLElement>) => {
|
|
99
|
+
children.props.onClick?.(event);
|
|
100
|
+
|
|
101
|
+
if (disabled) return;
|
|
102
|
+
|
|
103
|
+
setIsConfirmed(true);
|
|
104
|
+
clearConfirmationTimeout();
|
|
105
|
+
timeoutRef.current = setTimeout(() => {
|
|
106
|
+
setIsConfirmed(false);
|
|
107
|
+
timeoutRef.current = null;
|
|
108
|
+
}, durationMs);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const originalAriaLabel = children.props['aria-label'];
|
|
112
|
+
const clonedChild = cloneElement(children, {
|
|
113
|
+
onClick: handleClick,
|
|
114
|
+
...(confirmedAriaLabel
|
|
115
|
+
? { 'aria-label': isConfirmed ? confirmedAriaLabel : originalAriaLabel }
|
|
116
|
+
: {}),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<Tooltip
|
|
121
|
+
label={label}
|
|
122
|
+
opened={!disabled && isConfirmed}
|
|
123
|
+
position={position}
|
|
124
|
+
withArrow={withArrow}
|
|
125
|
+
color={color}
|
|
126
|
+
withinPortal={withinPortal}
|
|
127
|
+
transitionProps={transitionProps}
|
|
128
|
+
>
|
|
129
|
+
{clonedChild}
|
|
130
|
+
</Tooltip>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
|
|
3
|
+
import { DataDialog } from './DataDialog';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* -- This file was auto-generated by Code Connect --
|
|
7
|
+
* None of your props could be automatically mapped to Figma properties.
|
|
8
|
+
* You should update the `props` object to include a mapping from your
|
|
9
|
+
* code props to Figma properties, and update the `example` function to
|
|
10
|
+
* return the code example you'd like to see in Figma
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
figma.connect(
|
|
14
|
+
DataDialog,
|
|
15
|
+
'https://www.figma.com/design/VCLfybgU3OaUUPrQdBaVmP/LM-Design-System?node-id=151%3A12298',
|
|
16
|
+
{
|
|
17
|
+
props: {
|
|
18
|
+
// No matching props could be found for these Figma properties:
|
|
19
|
+
// "showError": figma.boolean('ShowError'),
|
|
20
|
+
// "type": figma.enum('Type', {
|
|
21
|
+
// "Desktop": "desktop",
|
|
22
|
+
// "Desktop Scrollable": "desktop-scrollable",
|
|
23
|
+
// "Mobile": "mobile",
|
|
24
|
+
// "Mobile Full Screen Scrollable": "mobile-full-screen-scrollable"
|
|
25
|
+
// })
|
|
26
|
+
},
|
|
27
|
+
example: _props => (
|
|
28
|
+
<DataDialog open onOpenChange={() => {}} title="Dialog title">
|
|
29
|
+
Dialog content
|
|
30
|
+
</DataDialog>
|
|
31
|
+
),
|
|
32
|
+
}
|
|
33
|
+
);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Modal } from '@mantine/core';
|
|
4
|
+
|
|
5
|
+
import { textStyleVariants } from '../tokens';
|
|
6
|
+
|
|
7
|
+
import { Text } from './Typography';
|
|
8
|
+
|
|
9
|
+
export interface DataDialogProps {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onOpenChange: (open: boolean) => void;
|
|
12
|
+
title: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const titleStyle: CSSProperties = textStyleVariants.heading4;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* DataDialog component for displaying detailed data in a modal
|
|
21
|
+
* Wraps Mantine Modal with a consistent API
|
|
22
|
+
*/
|
|
23
|
+
export function DataDialog({
|
|
24
|
+
open,
|
|
25
|
+
onOpenChange,
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
children,
|
|
29
|
+
}: DataDialogProps) {
|
|
30
|
+
return (
|
|
31
|
+
<Modal
|
|
32
|
+
opened={open}
|
|
33
|
+
onClose={() => onOpenChange(false)}
|
|
34
|
+
title={<span style={titleStyle}>{title}</span>}
|
|
35
|
+
size="md"
|
|
36
|
+
centered
|
|
37
|
+
>
|
|
38
|
+
{description && (
|
|
39
|
+
<Text variant="caption1" c="text.subdued.default" mb="md">
|
|
40
|
+
{description}
|
|
41
|
+
</Text>
|
|
42
|
+
)}
|
|
43
|
+
{children}
|
|
44
|
+
</Modal>
|
|
45
|
+
);
|
|
46
|
+
}
|