@ttoss/components 2.14.19 → 2.14.21
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/dist/Accordion/index.d.mts +157 -0
- package/dist/Accordion/index.mjs +175 -0
- package/dist/DatePicker/index.d.mts +26 -0
- package/dist/DatePicker/index.mjs +339 -0
- package/dist/Drawer/index.d.mts +17 -0
- package/dist/{esm/Drawer/index.js → Drawer/index.mjs} +21 -14
- package/dist/EnhancedTitle/{index.d.ts → index.d.mts} +57 -47
- package/dist/EnhancedTitle/index.mjs +234 -0
- package/dist/FileUploader/index.d.mts +77 -0
- package/dist/FileUploader/index.mjs +386 -0
- package/dist/InstallPwa/index.d.mts +13 -0
- package/dist/InstallPwa/index.mjs +64 -0
- package/dist/JsonEditor/index.d.mts +3 -0
- package/dist/{esm/JsonEditor/index.js → JsonEditor/index.mjs} +0 -3
- package/dist/JsonView/index.d.mts +3 -0
- package/dist/{esm/JsonView/index.js → JsonView/index.mjs} +0 -3
- package/dist/List/{index.d.ts → index.d.mts} +9 -6
- package/dist/List/index.mjs +34 -0
- package/dist/LockedOverlay/index.d.mts +162 -0
- package/dist/LockedOverlay/index.mjs +386 -0
- package/dist/Markdown/index.d.mts +16 -0
- package/dist/Markdown/index.mjs +26 -0
- package/dist/Menu/index.d.mts +16 -0
- package/dist/{esm/Menu/index.js → Menu/index.mjs} +56 -51
- package/dist/MetricCard/index.d.mts +153 -0
- package/dist/MetricCard/index.mjs +408 -0
- package/dist/Modal/index.d.mts +11 -0
- package/dist/{esm/Modal/index.js → Modal/index.mjs} +11 -12
- package/dist/NavList/index.d.mts +64 -0
- package/dist/{esm/NavList/index.js → NavList/index.mjs} +79 -73
- package/dist/NotificationCard/index.d.mts +22 -0
- package/dist/NotificationCard/index.mjs +173 -0
- package/dist/NotificationsMenu/index.d.mts +47 -0
- package/dist/NotificationsMenu/index.mjs +380 -0
- package/dist/Search/index.d.mts +18 -0
- package/dist/{esm/Search/index.js → Search/index.mjs} +11 -9
- package/dist/SpotlightCard/index.d.mts +36 -0
- package/dist/SpotlightCard/index.mjs +219 -0
- package/dist/Table/index.d.mts +17 -0
- package/dist/Table/index.mjs +64 -0
- package/dist/Tabs/index.d.mts +17 -0
- package/dist/{esm/Tabs/index.js → Tabs/index.mjs} +24 -12
- package/dist/Toast/index.d.mts +8 -0
- package/dist/Toast/index.mjs +43 -0
- package/package.json +15 -15
- package/dist/Accordion/index.d.ts +0 -148
- package/dist/DatePicker/index.d.ts +0 -20
- package/dist/Drawer/index.d.ts +0 -12
- package/dist/FileUploader/index.d.ts +0 -55
- package/dist/InstallPwa/index.d.ts +0 -10
- package/dist/JsonEditor/index.d.ts +0 -2
- package/dist/JsonView/index.d.ts +0 -1
- package/dist/LockedOverlay/index.d.ts +0 -151
- package/dist/Markdown/index.d.ts +0 -11
- package/dist/Menu/index.d.ts +0 -11
- package/dist/MetricCard/index.d.ts +0 -148
- package/dist/Modal/index.d.ts +0 -10
- package/dist/NavList/index.d.ts +0 -55
- package/dist/NotificationCard/index.d.ts +0 -21
- package/dist/NotificationsMenu/index.d.ts +0 -36
- package/dist/Search/index.d.ts +0 -11
- package/dist/SpotlightCard/index.d.ts +0 -27
- package/dist/Table/index.d.ts +0 -16
- package/dist/esm/Accordion/index.js +0 -119
- package/dist/esm/DatePicker/index.js +0 -331
- package/dist/esm/EnhancedTitle/index.js +0 -190
- package/dist/esm/FileUploader/index.js +0 -401
- package/dist/esm/InstallPwa/index.js +0 -61
- package/dist/esm/List/index.js +0 -30
- package/dist/esm/LockedOverlay/index.js +0 -316
- package/dist/esm/Markdown/index.js +0 -23
- package/dist/esm/MetricCard/index.js +0 -327
- package/dist/esm/NotificationCard/index.js +0 -156
- package/dist/esm/NotificationsMenu/index.js +0 -359
- package/dist/esm/SpotlightCard/index.js +0 -212
- package/dist/esm/Table/index.js +0 -63
- package/dist/esm/Toast/index.js +0 -38
- package/dist/esm/chunk-V4MHYKRI.js +0 -7
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { ButtonProps, Theme, ThemeUIStyleObject } from "@ttoss/ui";
|
|
4
|
+
|
|
5
|
+
//#region src/components/LockedOverlay/LockedOverlay.d.ts
|
|
6
|
+
type LockedOverlayAction = {
|
|
7
|
+
/**
|
|
8
|
+
* Label text for the button
|
|
9
|
+
*/
|
|
10
|
+
label: string;
|
|
11
|
+
/**
|
|
12
|
+
* Icon identifier from @ttoss/react-icons
|
|
13
|
+
*/
|
|
14
|
+
icon?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Button variant
|
|
17
|
+
*/
|
|
18
|
+
variant: 'primary' | 'accent' | 'secondary';
|
|
19
|
+
/**
|
|
20
|
+
* Click handler for the button
|
|
21
|
+
*/
|
|
22
|
+
onClick: () => void;
|
|
23
|
+
};
|
|
24
|
+
type LockedOverlayProps = {
|
|
25
|
+
/**
|
|
26
|
+
* Controls the overlay visibility
|
|
27
|
+
*/
|
|
28
|
+
isOpen: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Optional close handler. If not provided, overlay cannot be closed by user interaction
|
|
31
|
+
*/
|
|
32
|
+
onRequestClose?: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Header configuration for the SpotlightCard
|
|
35
|
+
*/
|
|
36
|
+
header: {
|
|
37
|
+
/**
|
|
38
|
+
* Icon identifier from @ttoss/react-icons
|
|
39
|
+
*/
|
|
40
|
+
icon: string;
|
|
41
|
+
/**
|
|
42
|
+
* Title text for the header
|
|
43
|
+
*/
|
|
44
|
+
title: string;
|
|
45
|
+
/**
|
|
46
|
+
* Description text for the header
|
|
47
|
+
*/
|
|
48
|
+
description: string;
|
|
49
|
+
/**
|
|
50
|
+
* Visual variant for the SpotlightCard
|
|
51
|
+
* @default 'primary'
|
|
52
|
+
*/
|
|
53
|
+
variant?: 'primary' | 'accent';
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Optional first button to display in the SpotlightCard header
|
|
57
|
+
*/
|
|
58
|
+
firstButton?: ButtonProps | React.ReactNode;
|
|
59
|
+
/**
|
|
60
|
+
* Optional second button to display in the SpotlightCard header
|
|
61
|
+
*/
|
|
62
|
+
secondButton?: ButtonProps | React.ReactNode;
|
|
63
|
+
/**
|
|
64
|
+
* Content to be rendered in the overlay body
|
|
65
|
+
*/
|
|
66
|
+
children: React.ReactNode;
|
|
67
|
+
/**
|
|
68
|
+
* Optional list of actions to render as buttons in the footer
|
|
69
|
+
*/
|
|
70
|
+
actions?: LockedOverlayAction[];
|
|
71
|
+
/**
|
|
72
|
+
* Optional style overrides for the overlay and content container
|
|
73
|
+
*/
|
|
74
|
+
sx?: ThemeUIStyleObject<Theme<object>>;
|
|
75
|
+
/**
|
|
76
|
+
* Optional z-index value to control overlay stacking order.
|
|
77
|
+
* The overlay will appear above the parent container content.
|
|
78
|
+
* @default 1
|
|
79
|
+
*
|
|
80
|
+
* zIndex hierarchy reference:
|
|
81
|
+
* - modal: 1400
|
|
82
|
+
* - overlay: 1300 (sidebar layouts use this value)
|
|
83
|
+
* - dropdown: 1000
|
|
84
|
+
* - sticky: 1100
|
|
85
|
+
* - banner: 1200
|
|
86
|
+
*/
|
|
87
|
+
zIndex?: string | number;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* LockedOverlay is a component for blocking and displaying locked features or restricted content
|
|
91
|
+
* within a specific container.
|
|
92
|
+
*
|
|
93
|
+
* This component renders as an absolutely positioned overlay that blocks the parent container's content.
|
|
94
|
+
* The parent container must have `position: relative` for proper positioning.
|
|
95
|
+
*
|
|
96
|
+
* Unlike a modal, this component blocks only its parent container, not the entire viewport,
|
|
97
|
+
* making it ideal for blocking specific sections like Layout.Main, Layout.Main.Body, etc.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```tsx
|
|
101
|
+
* // Parent container must have position: relative
|
|
102
|
+
* <Layout.Main sx={{ position: 'relative' }}>
|
|
103
|
+
* <LockedOverlay
|
|
104
|
+
* isOpen={isOpen}
|
|
105
|
+
* onRequestClose={() => setIsOpen(false)}
|
|
106
|
+
* header={{
|
|
107
|
+
* icon: "fluent:lock-closed-24-filled",
|
|
108
|
+
* title: "Premium Feature",
|
|
109
|
+
* description: "Available in Pro plan only",
|
|
110
|
+
* variant: "primary"
|
|
111
|
+
* }}
|
|
112
|
+
* actions={[
|
|
113
|
+
* {
|
|
114
|
+
* label: "Upgrade Now",
|
|
115
|
+
* icon: "fluent-emoji-high-contrast:sparkles",
|
|
116
|
+
* variant: "primary",
|
|
117
|
+
* onClick: handleUpgrade
|
|
118
|
+
* },
|
|
119
|
+
* {
|
|
120
|
+
* label: "Learn More",
|
|
121
|
+
* icon: "fluent:arrow-right-16-regular",
|
|
122
|
+
* variant: "accent",
|
|
123
|
+
* onClick: handleLearnMore
|
|
124
|
+
* }
|
|
125
|
+
* ]}
|
|
126
|
+
* >
|
|
127
|
+
* <Text>This feature is only available for Pro users.</Text>
|
|
128
|
+
* </LockedOverlay>
|
|
129
|
+
* </Layout.Main>
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```tsx
|
|
134
|
+
* // Blocking a specific section with custom zIndex
|
|
135
|
+
* <Box sx={{ position: 'relative' }}>
|
|
136
|
+
* <LockedOverlay
|
|
137
|
+
* isOpen={isOpen}
|
|
138
|
+
* zIndex={10}
|
|
139
|
+
* header={{
|
|
140
|
+
* icon: "fluent:lock-closed-24-filled",
|
|
141
|
+
* title: "Feature Locked",
|
|
142
|
+
* description: "Unlock this feature"
|
|
143
|
+
* }}
|
|
144
|
+
* >
|
|
145
|
+
* <Text>Content here</Text>
|
|
146
|
+
* </LockedOverlay>
|
|
147
|
+
* </Box>
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
declare const LockedOverlay: ({
|
|
151
|
+
isOpen,
|
|
152
|
+
onRequestClose,
|
|
153
|
+
header,
|
|
154
|
+
firstButton,
|
|
155
|
+
secondButton,
|
|
156
|
+
children,
|
|
157
|
+
actions,
|
|
158
|
+
sx,
|
|
159
|
+
zIndex
|
|
160
|
+
}: LockedOverlayProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
161
|
+
//#endregion
|
|
162
|
+
export { LockedOverlay };
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Icon } from "@ttoss/react-icons";
|
|
5
|
+
import { Box, Button, Card, Flex, Text, keyframes } from "@ttoss/ui";
|
|
6
|
+
|
|
7
|
+
//#region src/components/SpotlightCard/SpotlightCard.tsx
|
|
8
|
+
const SpotlightCard = ({
|
|
9
|
+
icon,
|
|
10
|
+
title,
|
|
11
|
+
badge,
|
|
12
|
+
description,
|
|
13
|
+
firstButton,
|
|
14
|
+
secondButton,
|
|
15
|
+
variant = "accent"
|
|
16
|
+
}) => {
|
|
17
|
+
const gradientFlow = keyframes({
|
|
18
|
+
"0%": {
|
|
19
|
+
backgroundPosition: "0% 50%"
|
|
20
|
+
},
|
|
21
|
+
"50%": {
|
|
22
|
+
backgroundPosition: "100% 50%"
|
|
23
|
+
},
|
|
24
|
+
"100%": {
|
|
25
|
+
backgroundPosition: "0% 50%"
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const hasButtons = !!firstButton || !!secondButton;
|
|
29
|
+
const isAccent = variant === "accent";
|
|
30
|
+
const textColorToken = isAccent ? "action.text.accent.default" : "action.text.primary.default";
|
|
31
|
+
const iconColorToken = isAccent ? "action.text.accent.default" : "display.text.accent.default";
|
|
32
|
+
const iconBgToken = isAccent ? "rgba(255,255,255,0.3)" : "action.background.secondary.default";
|
|
33
|
+
const badgeBgToken = isAccent ? "action.background.primary.default" : "action.background.accent.default";
|
|
34
|
+
const badgeTextToken = isAccent ? "action.text.primary.default" : "action.text.accent.default";
|
|
35
|
+
const btnPrimaryVariant = isAccent ? "primary" : "accent";
|
|
36
|
+
const btnPrimaryColorToken = isAccent ? "action.text.primary.default" : "action.text.accent.default";
|
|
37
|
+
const btnSecondaryColorToken = textColorToken;
|
|
38
|
+
const btnSecondaryBorderColorToken = isAccent ? "currentColor" : "display.border.muted.default";
|
|
39
|
+
const renderButton = (prop, config) => {
|
|
40
|
+
if (!prop) return null;
|
|
41
|
+
if (React.isValidElement(prop)) return prop;
|
|
42
|
+
if (typeof prop !== "object") return prop;
|
|
43
|
+
const {
|
|
44
|
+
sx,
|
|
45
|
+
...rest
|
|
46
|
+
} = prop;
|
|
47
|
+
const {
|
|
48
|
+
variant: defaultVariant,
|
|
49
|
+
textColor,
|
|
50
|
+
styles = {}
|
|
51
|
+
} = config;
|
|
52
|
+
return /* @__PURE__ */jsx(Button, {
|
|
53
|
+
variant: defaultVariant,
|
|
54
|
+
sx: {
|
|
55
|
+
display: "flex",
|
|
56
|
+
alignItems: "center",
|
|
57
|
+
justifyContent: "center",
|
|
58
|
+
gap: "2",
|
|
59
|
+
px: "6",
|
|
60
|
+
py: "3",
|
|
61
|
+
fontSize: "15px",
|
|
62
|
+
fontWeight: "bold",
|
|
63
|
+
whiteSpace: "nowrap",
|
|
64
|
+
transition: "all 0.2s",
|
|
65
|
+
color: textColor,
|
|
66
|
+
...styles,
|
|
67
|
+
...sx
|
|
68
|
+
},
|
|
69
|
+
...rest
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
return /* @__PURE__ */jsxs(Card, {
|
|
73
|
+
sx: {
|
|
74
|
+
display: "flex",
|
|
75
|
+
flexDirection: ["row"],
|
|
76
|
+
flexWrap: "nowrap",
|
|
77
|
+
alignItems: "center",
|
|
78
|
+
justifyContent: "space-between",
|
|
79
|
+
background: t => {
|
|
80
|
+
const theme = t;
|
|
81
|
+
const bgStart = isAccent ? theme.colors?.action?.background?.accent?.default : theme.colors?.action?.background?.primary?.default;
|
|
82
|
+
const bgMiddle = isAccent ? theme.colors?.action?.background?.accent?.active : theme.colors?.action?.background?.secondary?.default;
|
|
83
|
+
if (isAccent) return `linear-gradient(270deg, transparent 0%, rgba(255,255,255,0.4) 50%, transparent 100%),
|
|
84
|
+
linear-gradient(0deg, ${bgStart}, ${bgStart})`;
|
|
85
|
+
return `linear-gradient(270deg, ${bgStart}, ${bgMiddle}, ${bgStart})`;
|
|
86
|
+
},
|
|
87
|
+
backgroundSize: isAccent ? "200% 100%, auto" : "400% 400%",
|
|
88
|
+
animation: `${gradientFlow} 6s ease infinite`,
|
|
89
|
+
width: "100%",
|
|
90
|
+
minHeight: "104px",
|
|
91
|
+
borderRadius: "xl",
|
|
92
|
+
boxShadow: "0 4px 20px rgba(0,0,0,0.1)",
|
|
93
|
+
py: "7",
|
|
94
|
+
px: "8",
|
|
95
|
+
gap: "5",
|
|
96
|
+
color: textColorToken,
|
|
97
|
+
overflow: "hidden",
|
|
98
|
+
borderWidth: "1px",
|
|
99
|
+
borderStyle: "solid",
|
|
100
|
+
borderColor: isAccent ? "transparent" : "display.border.muted.default"
|
|
101
|
+
},
|
|
102
|
+
"data-testid": "spotlight-card",
|
|
103
|
+
children: [/* @__PURE__ */jsxs(Flex, {
|
|
104
|
+
sx: {
|
|
105
|
+
alignItems: "center",
|
|
106
|
+
gap: "5",
|
|
107
|
+
flex: 1,
|
|
108
|
+
minWidth: 0
|
|
109
|
+
},
|
|
110
|
+
children: [/* @__PURE__ */jsx(Box, {
|
|
111
|
+
sx: {
|
|
112
|
+
width: 64,
|
|
113
|
+
height: 64,
|
|
114
|
+
borderRadius: "2xl",
|
|
115
|
+
backgroundColor: iconBgToken,
|
|
116
|
+
display: "flex",
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
justifyContent: "center",
|
|
119
|
+
flexShrink: 0,
|
|
120
|
+
color: iconColorToken
|
|
121
|
+
},
|
|
122
|
+
children: /* @__PURE__ */jsx(Icon, {
|
|
123
|
+
icon,
|
|
124
|
+
width: 32
|
|
125
|
+
})
|
|
126
|
+
}), /* @__PURE__ */jsxs(Box, {
|
|
127
|
+
sx: {
|
|
128
|
+
minWidth: 0
|
|
129
|
+
},
|
|
130
|
+
children: [/* @__PURE__ */jsxs(Text, {
|
|
131
|
+
as: "div",
|
|
132
|
+
sx: {
|
|
133
|
+
fontFamily: "mono",
|
|
134
|
+
fontSize: "32px",
|
|
135
|
+
lineHeight: 1.1,
|
|
136
|
+
color: "inherit",
|
|
137
|
+
whiteSpace: "nowrap",
|
|
138
|
+
display: "flex",
|
|
139
|
+
alignItems: "center",
|
|
140
|
+
gap: "3"
|
|
141
|
+
},
|
|
142
|
+
children: [title, badge && /* @__PURE__ */jsx(Box, {
|
|
143
|
+
as: "span",
|
|
144
|
+
sx: {
|
|
145
|
+
backgroundColor: badgeBgToken,
|
|
146
|
+
color: badgeTextToken,
|
|
147
|
+
fontFamily: "mono",
|
|
148
|
+
fontWeight: "bold",
|
|
149
|
+
fontSize: "11px",
|
|
150
|
+
lineHeight: 1,
|
|
151
|
+
paddingX: "6px",
|
|
152
|
+
paddingY: "3px",
|
|
153
|
+
borderRadius: "md",
|
|
154
|
+
textTransform: "uppercase",
|
|
155
|
+
letterSpacing: "0.05em",
|
|
156
|
+
display: "inline-flex",
|
|
157
|
+
alignItems: "center",
|
|
158
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
159
|
+
transform: "translateY(3px)"
|
|
160
|
+
},
|
|
161
|
+
children: badge
|
|
162
|
+
})]
|
|
163
|
+
}), /* @__PURE__ */jsx(Text, {
|
|
164
|
+
as: "div",
|
|
165
|
+
sx: {
|
|
166
|
+
fontFamily: "body",
|
|
167
|
+
fontWeight: 400,
|
|
168
|
+
fontSize: "16px",
|
|
169
|
+
color: "inherit",
|
|
170
|
+
opacity: .9,
|
|
171
|
+
mt: "1",
|
|
172
|
+
overflow: "hidden",
|
|
173
|
+
textOverflow: "ellipsis",
|
|
174
|
+
display: "-webkit-box",
|
|
175
|
+
WebkitLineClamp: 2,
|
|
176
|
+
WebkitBoxOrient: "vertical"
|
|
177
|
+
},
|
|
178
|
+
children: description
|
|
179
|
+
})]
|
|
180
|
+
})]
|
|
181
|
+
}), hasButtons && /* @__PURE__ */jsxs(Flex, {
|
|
182
|
+
sx: {
|
|
183
|
+
gap: "4",
|
|
184
|
+
alignItems: "center",
|
|
185
|
+
flexShrink: 0,
|
|
186
|
+
ml: "auto"
|
|
187
|
+
},
|
|
188
|
+
children: [renderButton(firstButton, {
|
|
189
|
+
variant: btnPrimaryVariant,
|
|
190
|
+
textColor: btnPrimaryColorToken,
|
|
191
|
+
styles: {
|
|
192
|
+
":hover": {
|
|
193
|
+
transform: "translateY(-1px)"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}), renderButton(secondButton, {
|
|
197
|
+
variant: "secondary",
|
|
198
|
+
textColor: btnSecondaryColorToken,
|
|
199
|
+
styles: {
|
|
200
|
+
backgroundColor: "transparent",
|
|
201
|
+
borderWidth: "1px",
|
|
202
|
+
borderStyle: "solid",
|
|
203
|
+
borderColor: btnSecondaryBorderColorToken,
|
|
204
|
+
opacity: isAccent ? .6 : 1,
|
|
205
|
+
cursor: "pointer",
|
|
206
|
+
":hover": {
|
|
207
|
+
backgroundColor: "rgba(255,255,255,0.2)",
|
|
208
|
+
opacity: 1,
|
|
209
|
+
borderColor: btnSecondaryBorderColorToken
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
})]
|
|
213
|
+
})]
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
SpotlightCard.displayName = "SpotlightCard";
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/components/LockedOverlay/LockedOverlay.tsx
|
|
220
|
+
/**
|
|
221
|
+
* LockedOverlay is a component for blocking and displaying locked features or restricted content
|
|
222
|
+
* within a specific container.
|
|
223
|
+
*
|
|
224
|
+
* This component renders as an absolutely positioned overlay that blocks the parent container's content.
|
|
225
|
+
* The parent container must have `position: relative` for proper positioning.
|
|
226
|
+
*
|
|
227
|
+
* Unlike a modal, this component blocks only its parent container, not the entire viewport,
|
|
228
|
+
* making it ideal for blocking specific sections like Layout.Main, Layout.Main.Body, etc.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```tsx
|
|
232
|
+
* // Parent container must have position: relative
|
|
233
|
+
* <Layout.Main sx={{ position: 'relative' }}>
|
|
234
|
+
* <LockedOverlay
|
|
235
|
+
* isOpen={isOpen}
|
|
236
|
+
* onRequestClose={() => setIsOpen(false)}
|
|
237
|
+
* header={{
|
|
238
|
+
* icon: "fluent:lock-closed-24-filled",
|
|
239
|
+
* title: "Premium Feature",
|
|
240
|
+
* description: "Available in Pro plan only",
|
|
241
|
+
* variant: "primary"
|
|
242
|
+
* }}
|
|
243
|
+
* actions={[
|
|
244
|
+
* {
|
|
245
|
+
* label: "Upgrade Now",
|
|
246
|
+
* icon: "fluent-emoji-high-contrast:sparkles",
|
|
247
|
+
* variant: "primary",
|
|
248
|
+
* onClick: handleUpgrade
|
|
249
|
+
* },
|
|
250
|
+
* {
|
|
251
|
+
* label: "Learn More",
|
|
252
|
+
* icon: "fluent:arrow-right-16-regular",
|
|
253
|
+
* variant: "accent",
|
|
254
|
+
* onClick: handleLearnMore
|
|
255
|
+
* }
|
|
256
|
+
* ]}
|
|
257
|
+
* >
|
|
258
|
+
* <Text>This feature is only available for Pro users.</Text>
|
|
259
|
+
* </LockedOverlay>
|
|
260
|
+
* </Layout.Main>
|
|
261
|
+
* ```
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```tsx
|
|
265
|
+
* // Blocking a specific section with custom zIndex
|
|
266
|
+
* <Box sx={{ position: 'relative' }}>
|
|
267
|
+
* <LockedOverlay
|
|
268
|
+
* isOpen={isOpen}
|
|
269
|
+
* zIndex={10}
|
|
270
|
+
* header={{
|
|
271
|
+
* icon: "fluent:lock-closed-24-filled",
|
|
272
|
+
* title: "Feature Locked",
|
|
273
|
+
* description: "Unlock this feature"
|
|
274
|
+
* }}
|
|
275
|
+
* >
|
|
276
|
+
* <Text>Content here</Text>
|
|
277
|
+
* </LockedOverlay>
|
|
278
|
+
* </Box>
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
const LockedOverlay = ({
|
|
282
|
+
isOpen,
|
|
283
|
+
onRequestClose,
|
|
284
|
+
header,
|
|
285
|
+
firstButton,
|
|
286
|
+
secondButton,
|
|
287
|
+
children,
|
|
288
|
+
actions,
|
|
289
|
+
sx,
|
|
290
|
+
zIndex = 1
|
|
291
|
+
}) => {
|
|
292
|
+
const content = /* @__PURE__ */jsxs(Card, {
|
|
293
|
+
className: "lockedoverlay-card",
|
|
294
|
+
role: "dialog",
|
|
295
|
+
"aria-modal": true,
|
|
296
|
+
sx: {
|
|
297
|
+
width: "full",
|
|
298
|
+
maxWidth: "620px",
|
|
299
|
+
borderRadius: "lg",
|
|
300
|
+
overflow: "auto",
|
|
301
|
+
border: "none",
|
|
302
|
+
boxShadow: "none"
|
|
303
|
+
},
|
|
304
|
+
children: [/* @__PURE__ */jsx(Flex, {
|
|
305
|
+
sx: {
|
|
306
|
+
width: "full",
|
|
307
|
+
paddingX: "6",
|
|
308
|
+
paddingY: "4"
|
|
309
|
+
},
|
|
310
|
+
children: /* @__PURE__ */jsx(SpotlightCard, {
|
|
311
|
+
icon: header.icon,
|
|
312
|
+
title: header.title,
|
|
313
|
+
description: header.description,
|
|
314
|
+
variant: header.variant || "primary",
|
|
315
|
+
firstButton,
|
|
316
|
+
secondButton
|
|
317
|
+
})
|
|
318
|
+
}), /* @__PURE__ */jsxs(Card.Body, {
|
|
319
|
+
sx: {
|
|
320
|
+
px: ["5", "7"],
|
|
321
|
+
py: ["6", "7"],
|
|
322
|
+
gap: "6",
|
|
323
|
+
width: "full"
|
|
324
|
+
},
|
|
325
|
+
children: [children, actions && actions.length > 0 && /* @__PURE__ */jsx(Card.Footer, {
|
|
326
|
+
children: /* @__PURE__ */jsx(Flex, {
|
|
327
|
+
className: "lockedoverlay-footer",
|
|
328
|
+
sx: {
|
|
329
|
+
flexDirection: "column",
|
|
330
|
+
gap: "4",
|
|
331
|
+
alignItems: "center",
|
|
332
|
+
width: "full",
|
|
333
|
+
paddingX: "6",
|
|
334
|
+
marginTop: "8"
|
|
335
|
+
},
|
|
336
|
+
children: actions.map((action, index) => {
|
|
337
|
+
return /* @__PURE__ */jsxs(Button, {
|
|
338
|
+
variant: action.variant,
|
|
339
|
+
onClick: action.onClick,
|
|
340
|
+
sx: {
|
|
341
|
+
width: "full",
|
|
342
|
+
justifyContent: "center"
|
|
343
|
+
},
|
|
344
|
+
children: [action.icon && /* @__PURE__ */jsx(Icon, {
|
|
345
|
+
icon: action.icon
|
|
346
|
+
}), action.label]
|
|
347
|
+
}, index);
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
})]
|
|
351
|
+
})]
|
|
352
|
+
});
|
|
353
|
+
if (!isOpen) return null;
|
|
354
|
+
return /* @__PURE__ */jsx(Flex, {
|
|
355
|
+
"data-testid": "lockedoverlay-overlay",
|
|
356
|
+
onClick: () => {
|
|
357
|
+
return onRequestClose?.();
|
|
358
|
+
},
|
|
359
|
+
sx: {
|
|
360
|
+
position: "absolute",
|
|
361
|
+
inset: 0,
|
|
362
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
363
|
+
display: "flex",
|
|
364
|
+
justifyContent: "center",
|
|
365
|
+
alignItems: "center",
|
|
366
|
+
zIndex,
|
|
367
|
+
...sx
|
|
368
|
+
},
|
|
369
|
+
children: /* @__PURE__ */jsx(Flex, {
|
|
370
|
+
onClick: event => {
|
|
371
|
+
event.stopPropagation();
|
|
372
|
+
},
|
|
373
|
+
sx: {
|
|
374
|
+
width: "full",
|
|
375
|
+
maxWidth: ["95%", "90%", "620px"],
|
|
376
|
+
maxHeight: "90%",
|
|
377
|
+
justifyContent: "center",
|
|
378
|
+
overflow: "auto"
|
|
379
|
+
},
|
|
380
|
+
children: content
|
|
381
|
+
})
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
//#endregion
|
|
386
|
+
export { LockedOverlay };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import { FlexProps } from "@ttoss/ui";
|
|
3
|
+
import { Options } from "react-markdown";
|
|
4
|
+
|
|
5
|
+
//#region src/components/Markdown/Markdown.d.ts
|
|
6
|
+
type MarkdownProps = Options & {
|
|
7
|
+
children: string;
|
|
8
|
+
sx?: FlexProps['sx'];
|
|
9
|
+
};
|
|
10
|
+
declare const Markdown: ({
|
|
11
|
+
children,
|
|
12
|
+
sx,
|
|
13
|
+
...props
|
|
14
|
+
}: MarkdownProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Markdown, MarkdownProps };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { BaseStyles } from "@ttoss/ui";
|
|
4
|
+
import ReactMarkdown from "react-markdown";
|
|
5
|
+
import rehypeRaw from "rehype-raw";
|
|
6
|
+
import remarkGfm from "remark-gfm";
|
|
7
|
+
|
|
8
|
+
//#region src/components/Markdown/Markdown.tsx
|
|
9
|
+
const Markdown = ({
|
|
10
|
+
children,
|
|
11
|
+
sx,
|
|
12
|
+
...props
|
|
13
|
+
}) => {
|
|
14
|
+
return /* @__PURE__ */jsx(BaseStyles, {
|
|
15
|
+
sx,
|
|
16
|
+
children: /* @__PURE__ */jsx(ReactMarkdown, {
|
|
17
|
+
rehypePlugins: [rehypeRaw],
|
|
18
|
+
remarkPlugins: [remarkGfm],
|
|
19
|
+
...props,
|
|
20
|
+
children
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Markdown };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/Menu/Menu.d.ts
|
|
5
|
+
type MenuProps = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
sx?: Record<string, unknown>;
|
|
8
|
+
menuIcon?: string;
|
|
9
|
+
};
|
|
10
|
+
declare const Menu: ({
|
|
11
|
+
children,
|
|
12
|
+
sx,
|
|
13
|
+
menuIcon
|
|
14
|
+
}: MenuProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Menu, MenuProps };
|