@momentumworld/ui-react 0.17.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/dist/chunk-2HQPCV2L.js +895 -0
- package/dist/chunk-2HQPCV2L.js.map +1 -0
- package/dist/form.d.ts +175 -0
- package/dist/form.js +356 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +2162 -0
- package/dist/index.js +11640 -0
- package/dist/index.js.map +1 -0
- package/dist/input-JCZs61MO.d.ts +24 -0
- package/package.json +90 -0
- package/src/components/form/checkbox-group-field.tsx +101 -0
- package/src/components/form/date-field.tsx +79 -0
- package/src/components/form/date-range-field.tsx +106 -0
- package/src/components/form/form-context.ts +10 -0
- package/src/components/form/form.tsx +54 -0
- package/src/components/form/number-field.tsx +69 -0
- package/src/components/form/select-field.tsx +76 -0
- package/src/components/form/submit-button.tsx +28 -0
- package/src/components/form/text-field.tsx +107 -0
- package/src/components/layout/dashboard-header.tsx +54 -0
- package/src/components/layout/dashboard-panel.tsx +34 -0
- package/src/components/layout/dashboard-topbar.tsx +221 -0
- package/src/components/theme-provider.tsx +403 -0
- package/src/components/ui/accordion.tsx +69 -0
- package/src/components/ui/alert-dialog.tsx +169 -0
- package/src/components/ui/alert.tsx +80 -0
- package/src/components/ui/animated-counter.tsx +109 -0
- package/src/components/ui/animated-theme-toggler.tsx +265 -0
- package/src/components/ui/app-store-buttons.tsx +182 -0
- package/src/components/ui/aspect-ratio.tsx +23 -0
- package/src/components/ui/aurora-orb.tsx +163 -0
- package/src/components/ui/aurora-text.tsx +76 -0
- package/src/components/ui/autocomplete.tsx +296 -0
- package/src/components/ui/avatar-group.tsx +150 -0
- package/src/components/ui/avatar.tsx +285 -0
- package/src/components/ui/badge-group.tsx +160 -0
- package/src/components/ui/badge.tsx +172 -0
- package/src/components/ui/breadcrumb.tsx +112 -0
- package/src/components/ui/button.tsx +77 -0
- package/src/components/ui/calendar.tsx +137 -0
- package/src/components/ui/card.tsx +244 -0
- package/src/components/ui/carousel.tsx +258 -0
- package/src/components/ui/chart.tsx +379 -0
- package/src/components/ui/chat-divider.tsx +67 -0
- package/src/components/ui/chat.tsx +494 -0
- package/src/components/ui/checkbox-group.tsx +16 -0
- package/src/components/ui/checkbox.tsx +82 -0
- package/src/components/ui/collapsible.tsx +45 -0
- package/src/components/ui/color-picker.tsx +389 -0
- package/src/components/ui/combobox.tsx +411 -0
- package/src/components/ui/command.tsx +264 -0
- package/src/components/ui/confetti.tsx +196 -0
- package/src/components/ui/context-menu.tsx +271 -0
- package/src/components/ui/context-meter.tsx +134 -0
- package/src/components/ui/credit-card.tsx +214 -0
- package/src/components/ui/data-table-paged.tsx +163 -0
- package/src/components/ui/date-picker.tsx +154 -0
- package/src/components/ui/dialog.tsx +196 -0
- package/src/components/ui/drawer.tsx +135 -0
- package/src/components/ui/empty.tsx +127 -0
- package/src/components/ui/fab.tsx +45 -0
- package/src/components/ui/featured-icon.tsx +149 -0
- package/src/components/ui/field.tsx +88 -0
- package/src/components/ui/fieldset.tsx +29 -0
- package/src/components/ui/form.tsx +17 -0
- package/src/components/ui/frame.tsx +82 -0
- package/src/components/ui/generic-empty.tsx +142 -0
- package/src/components/ui/group.tsx +97 -0
- package/src/components/ui/help-tip.tsx +94 -0
- package/src/components/ui/horizontal-scroll-fader.tsx +228 -0
- package/src/components/ui/input-group.tsx +102 -0
- package/src/components/ui/input-otp.tsx +96 -0
- package/src/components/ui/input.tsx +66 -0
- package/src/components/ui/item.tsx +198 -0
- package/src/components/ui/kbd.tsx +30 -0
- package/src/components/ui/label.tsx +28 -0
- package/src/components/ui/markdown.tsx +188 -0
- package/src/components/ui/menu.tsx +312 -0
- package/src/components/ui/menubar.tsx +93 -0
- package/src/components/ui/meter.tsx +67 -0
- package/src/components/ui/multi-select.tsx +308 -0
- package/src/components/ui/navigation-menu.tsx +143 -0
- package/src/components/ui/number-field.tsx +160 -0
- package/src/components/ui/pagination-controls.tsx +74 -0
- package/src/components/ui/pagination.tsx +149 -0
- package/src/components/ui/pipeline.tsx +102 -0
- package/src/components/ui/popover.tsx +119 -0
- package/src/components/ui/preview-card.tsx +55 -0
- package/src/components/ui/progress.tsx +289 -0
- package/src/components/ui/qr-code.tsx +150 -0
- package/src/components/ui/radio-group.tsx +103 -0
- package/src/components/ui/resizable.tsx +56 -0
- package/src/components/ui/scroll-area.tsx +90 -0
- package/src/components/ui/scroller.tsx +38 -0
- package/src/components/ui/section-header.tsx +118 -0
- package/src/components/ui/segmented-control.tsx +83 -0
- package/src/components/ui/select.tsx +181 -0
- package/src/components/ui/separator.tsx +23 -0
- package/src/components/ui/sheet.tsx +224 -0
- package/src/components/ui/sidebar.tsx +774 -0
- package/src/components/ui/skeleton.tsx +16 -0
- package/src/components/ui/slider.tsx +108 -0
- package/src/components/ui/smooth-scroll.tsx +206 -0
- package/src/components/ui/social-button.tsx +247 -0
- package/src/components/ui/spinner-on-demand.tsx +32 -0
- package/src/components/ui/spinner.tsx +18 -0
- package/src/components/ui/stat.tsx +187 -0
- package/src/components/ui/stepper.tsx +167 -0
- package/src/components/ui/switch.tsx +56 -0
- package/src/components/ui/table.tsx +126 -0
- package/src/components/ui/tabs.tsx +90 -0
- package/src/components/ui/tag.tsx +242 -0
- package/src/components/ui/target-countdown.tsx +46 -0
- package/src/components/ui/text-editor.tsx +313 -0
- package/src/components/ui/textarea.tsx +51 -0
- package/src/components/ui/thinking-orb.tsx +6 -0
- package/src/components/ui/time-picker.tsx +308 -0
- package/src/components/ui/timeline.tsx +116 -0
- package/src/components/ui/toast.tsx +268 -0
- package/src/components/ui/toggle-group.tsx +101 -0
- package/src/components/ui/toggle.tsx +45 -0
- package/src/components/ui/toolbar.tsx +89 -0
- package/src/components/ui/tooltip.tsx +102 -0
- package/src/components/ui/vertical-scroll-fader.tsx +250 -0
- package/src/components/ui/video-player.tsx +275 -0
- package/src/components/upload/avatar-upload-base.tsx +131 -0
- package/src/components/upload/image-upload-base.tsx +112 -0
- package/src/form.ts +17 -0
- package/src/index.ts +143 -0
- package/src/lib/hooks/use-callback-ref.ts +15 -0
- package/src/lib/hooks/use-first-render.ts +11 -0
- package/src/lib/hooks/use-hover.ts +53 -0
- package/src/lib/hooks/use-is-tab-active.ts +17 -0
- package/src/lib/hooks/use-media-query.ts +164 -0
- package/src/lib/utils/css.ts +6 -0
- package/src/styles.css +329 -0
- package/src/types/helpers.ts +24 -0
- package/src/types/react.d.ts +7 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
This file is adapted from next-themes to work with tanstack start.
|
|
5
|
+
next-themes can be found at https://github.com/pacocoursey/next-themes under the MIT license.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
createContext,
|
|
10
|
+
memo,
|
|
11
|
+
useCallback,
|
|
12
|
+
useContext,
|
|
13
|
+
useEffect,
|
|
14
|
+
useMemo,
|
|
15
|
+
useState,
|
|
16
|
+
} from "react";
|
|
17
|
+
|
|
18
|
+
interface ValueObject {
|
|
19
|
+
[themeName: string]: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UseThemeProps {
|
|
23
|
+
/** List of all available theme names */
|
|
24
|
+
themes: string[];
|
|
25
|
+
/** Forced theme name for the current page */
|
|
26
|
+
forcedTheme?: string | undefined;
|
|
27
|
+
/** Update the theme */
|
|
28
|
+
setTheme: React.Dispatch<React.SetStateAction<string>>;
|
|
29
|
+
/** Active theme name */
|
|
30
|
+
theme?: string | undefined;
|
|
31
|
+
/** If `enableSystem` is true and the active theme is "system", this returns whether the system preference resolved to "dark" or "light". Otherwise, identical to `theme` */
|
|
32
|
+
resolvedTheme?: string | undefined;
|
|
33
|
+
/** If enableSystem is true, returns the System theme preference ("dark" or "light"), regardless what the active theme is */
|
|
34
|
+
systemTheme?: "dark" | "light" | undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type Attribute = `data-${string}` | "class";
|
|
38
|
+
|
|
39
|
+
export interface ThemeProviderProps extends React.PropsWithChildren {
|
|
40
|
+
/** List of all available theme names */
|
|
41
|
+
themes?: string[] | undefined;
|
|
42
|
+
/** Forced theme name for the current page */
|
|
43
|
+
forcedTheme?: string | undefined;
|
|
44
|
+
/** Whether to switch between dark and light themes based on prefers-color-scheme */
|
|
45
|
+
enableSystem?: boolean | undefined;
|
|
46
|
+
/** Disable all CSS transitions when switching themes */
|
|
47
|
+
disableTransitionOnChange?: boolean | undefined;
|
|
48
|
+
/** Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttons */
|
|
49
|
+
enableColorScheme?: boolean | undefined;
|
|
50
|
+
/** Key used to store theme setting in localStorage */
|
|
51
|
+
storageKey?: string | undefined;
|
|
52
|
+
/** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */
|
|
53
|
+
defaultTheme?: string | undefined;
|
|
54
|
+
/** HTML attribute modified based on the active theme. Accepts `class`, `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.), or an array which could include both */
|
|
55
|
+
attribute?: Attribute | Attribute[] | undefined;
|
|
56
|
+
/** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */
|
|
57
|
+
value?: ValueObject | undefined;
|
|
58
|
+
/** Nonce string to pass to the inline script for CSP headers */
|
|
59
|
+
nonce?: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const colorSchemes = ["light", "dark"];
|
|
63
|
+
const MEDIA = "(prefers-color-scheme: dark)";
|
|
64
|
+
const isServer = typeof window === "undefined";
|
|
65
|
+
const ThemeContext = createContext<UseThemeProps | undefined>(undefined);
|
|
66
|
+
const defaultContext: UseThemeProps = { setTheme: (_) => {}, themes: [] };
|
|
67
|
+
|
|
68
|
+
export const useTheme = () => useContext(ThemeContext) ?? defaultContext;
|
|
69
|
+
|
|
70
|
+
export const ThemeProvider = (props: ThemeProviderProps): React.ReactNode => {
|
|
71
|
+
const context = useContext(ThemeContext);
|
|
72
|
+
|
|
73
|
+
// Ignore nested context providers, just passthrough children
|
|
74
|
+
if (context) return props.children;
|
|
75
|
+
return <Theme {...props} />;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const defaultThemes = ["light", "dark"];
|
|
79
|
+
|
|
80
|
+
export const ThemeContextOverride = ({
|
|
81
|
+
children,
|
|
82
|
+
value,
|
|
83
|
+
}: {
|
|
84
|
+
children: React.ReactNode;
|
|
85
|
+
value: string;
|
|
86
|
+
}) => {
|
|
87
|
+
const context = useContext(ThemeContext);
|
|
88
|
+
|
|
89
|
+
if (!context) return children;
|
|
90
|
+
return (
|
|
91
|
+
<ThemeContext.Provider
|
|
92
|
+
value={{
|
|
93
|
+
...context,
|
|
94
|
+
resolvedTheme: value,
|
|
95
|
+
forcedTheme: value,
|
|
96
|
+
theme: value,
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
{children}
|
|
100
|
+
</ThemeContext.Provider>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const Theme = ({
|
|
105
|
+
forcedTheme,
|
|
106
|
+
disableTransitionOnChange = false,
|
|
107
|
+
enableSystem = true,
|
|
108
|
+
enableColorScheme = true,
|
|
109
|
+
storageKey = "theme",
|
|
110
|
+
themes = defaultThemes,
|
|
111
|
+
defaultTheme = enableSystem ? "system" : "light",
|
|
112
|
+
attribute = "data-theme",
|
|
113
|
+
value,
|
|
114
|
+
children,
|
|
115
|
+
nonce,
|
|
116
|
+
}: ThemeProviderProps) => {
|
|
117
|
+
const [theme, setThemeState] = useState(() =>
|
|
118
|
+
getTheme(storageKey, defaultTheme),
|
|
119
|
+
);
|
|
120
|
+
const [resolvedTheme, setResolvedTheme] = useState(() =>
|
|
121
|
+
theme === "system" ? getSystemTheme() : theme,
|
|
122
|
+
);
|
|
123
|
+
const attrs = !value ? themes : Object.values(value);
|
|
124
|
+
|
|
125
|
+
// apply selected theme function (light, dark, system)
|
|
126
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Code is copied from the library
|
|
127
|
+
const applyTheme = useCallback((theme: string | undefined) => {
|
|
128
|
+
let resolved = theme;
|
|
129
|
+
if (!resolved) return;
|
|
130
|
+
|
|
131
|
+
// If theme is system, resolve it before setting theme
|
|
132
|
+
if (theme === "system" && enableSystem) {
|
|
133
|
+
resolved = getSystemTheme();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const name = value ? value[resolved] : resolved;
|
|
137
|
+
const enable = disableTransitionOnChange ? disableAnimation() : null;
|
|
138
|
+
const d = document.documentElement;
|
|
139
|
+
|
|
140
|
+
const handleAttribute = (attr: Attribute) => {
|
|
141
|
+
if (attr === "class") {
|
|
142
|
+
d.classList.remove(...attrs);
|
|
143
|
+
if (name) d.classList.add(name);
|
|
144
|
+
} else if (attr.startsWith("data-")) {
|
|
145
|
+
if (name) {
|
|
146
|
+
d.setAttribute(attr, name);
|
|
147
|
+
} else {
|
|
148
|
+
d.removeAttribute(attr);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
if (Array.isArray(attribute)) attribute.forEach(handleAttribute);
|
|
154
|
+
else handleAttribute(attribute);
|
|
155
|
+
|
|
156
|
+
if (enableColorScheme) {
|
|
157
|
+
const fallback = colorSchemes.includes(defaultTheme)
|
|
158
|
+
? defaultTheme
|
|
159
|
+
: null;
|
|
160
|
+
const colorScheme = colorSchemes.includes(resolved) ? resolved : fallback;
|
|
161
|
+
// @ts-expect-error
|
|
162
|
+
d.style.colorScheme = colorScheme;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
enable?.();
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
// Set theme state and save to local storage
|
|
169
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Code is copied from the library
|
|
170
|
+
const setTheme = useCallback(
|
|
171
|
+
// biome-ignore lint/suspicious/noExplicitAny: Code is copied from the library
|
|
172
|
+
(value: any) => {
|
|
173
|
+
const newTheme = typeof value === "function" ? value(theme) : value;
|
|
174
|
+
setThemeState(newTheme);
|
|
175
|
+
|
|
176
|
+
// Save to storage
|
|
177
|
+
try {
|
|
178
|
+
localStorage.setItem(storageKey, newTheme);
|
|
179
|
+
} catch {
|
|
180
|
+
// Unsupported
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
[theme],
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Code is copied from the library
|
|
187
|
+
const handleMediaQuery = useCallback(
|
|
188
|
+
(e: MediaQueryListEvent | MediaQueryList) => {
|
|
189
|
+
const resolved = getSystemTheme(e);
|
|
190
|
+
setResolvedTheme(resolved);
|
|
191
|
+
|
|
192
|
+
if (theme === "system" && enableSystem && !forcedTheme) {
|
|
193
|
+
applyTheme("system");
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
[theme, forcedTheme],
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// Always listen to System preference
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
const media = window.matchMedia(MEDIA);
|
|
202
|
+
|
|
203
|
+
// Intentionally use deprecated listener methods to support iOS & old browsers
|
|
204
|
+
media.addListener(handleMediaQuery);
|
|
205
|
+
handleMediaQuery(media);
|
|
206
|
+
|
|
207
|
+
return () => media.removeListener(handleMediaQuery);
|
|
208
|
+
}, [handleMediaQuery]);
|
|
209
|
+
|
|
210
|
+
// localStorage event handling, allow to sync theme changes between tabs
|
|
211
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: The code is copied
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
const handleStorage = (e: StorageEvent) => {
|
|
214
|
+
if (e.key !== storageKey) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// If default theme set, use it if localstorage === null (happens on local storage manual deletion)
|
|
219
|
+
const theme = e.newValue || defaultTheme;
|
|
220
|
+
setTheme(theme);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
window.addEventListener("storage", handleStorage);
|
|
224
|
+
return () => window.removeEventListener("storage", handleStorage);
|
|
225
|
+
}, [setTheme]);
|
|
226
|
+
|
|
227
|
+
// Whenever theme or forcedTheme changes, apply it
|
|
228
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: The code is copied
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
applyTheme(forcedTheme ?? theme);
|
|
231
|
+
}, [forcedTheme, theme]);
|
|
232
|
+
|
|
233
|
+
const providerValue = useMemo(
|
|
234
|
+
() => ({
|
|
235
|
+
theme,
|
|
236
|
+
setTheme,
|
|
237
|
+
forcedTheme,
|
|
238
|
+
themes: enableSystem ? [...themes, "system"] : themes,
|
|
239
|
+
resolvedTheme: theme === "system" ? resolvedTheme : theme,
|
|
240
|
+
systemTheme: (enableSystem ? resolvedTheme : undefined) as
|
|
241
|
+
| "light"
|
|
242
|
+
| "dark"
|
|
243
|
+
| undefined,
|
|
244
|
+
}),
|
|
245
|
+
[theme, setTheme, forcedTheme, enableSystem, themes, resolvedTheme],
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<ThemeContext.Provider value={providerValue}>
|
|
250
|
+
<ThemeScript
|
|
251
|
+
{...{
|
|
252
|
+
forcedTheme,
|
|
253
|
+
storageKey,
|
|
254
|
+
attribute,
|
|
255
|
+
enableSystem,
|
|
256
|
+
enableColorScheme,
|
|
257
|
+
defaultTheme,
|
|
258
|
+
value,
|
|
259
|
+
themes,
|
|
260
|
+
nonce,
|
|
261
|
+
}}
|
|
262
|
+
/>
|
|
263
|
+
{children}
|
|
264
|
+
</ThemeContext.Provider>
|
|
265
|
+
);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const ThemeScript = memo(
|
|
269
|
+
({
|
|
270
|
+
forcedTheme,
|
|
271
|
+
storageKey,
|
|
272
|
+
attribute,
|
|
273
|
+
enableSystem,
|
|
274
|
+
enableColorScheme,
|
|
275
|
+
defaultTheme,
|
|
276
|
+
value,
|
|
277
|
+
themes,
|
|
278
|
+
nonce,
|
|
279
|
+
}: Omit<ThemeProviderProps, "children"> & { defaultTheme: string }) => {
|
|
280
|
+
const scriptArgs = JSON.stringify([
|
|
281
|
+
attribute,
|
|
282
|
+
storageKey,
|
|
283
|
+
defaultTheme,
|
|
284
|
+
forcedTheme,
|
|
285
|
+
themes,
|
|
286
|
+
value,
|
|
287
|
+
enableSystem,
|
|
288
|
+
enableColorScheme,
|
|
289
|
+
]).slice(1, -1);
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<script
|
|
293
|
+
suppressHydrationWarning
|
|
294
|
+
nonce={typeof window === "undefined" ? nonce : ""}
|
|
295
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: Needed to inject script before hydration
|
|
296
|
+
dangerouslySetInnerHTML={{
|
|
297
|
+
__html: `(${script.toString()})(${scriptArgs})`,
|
|
298
|
+
}}
|
|
299
|
+
/>
|
|
300
|
+
// <></>
|
|
301
|
+
);
|
|
302
|
+
},
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// Helpers
|
|
306
|
+
const getTheme = (key: string, fallback?: string) => {
|
|
307
|
+
if (isServer) return undefined;
|
|
308
|
+
let theme: string | undefined;
|
|
309
|
+
try {
|
|
310
|
+
theme = localStorage.getItem(key) || undefined;
|
|
311
|
+
} catch {
|
|
312
|
+
// Unsupported
|
|
313
|
+
}
|
|
314
|
+
return theme || fallback;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const disableAnimation = () => {
|
|
318
|
+
const css = document.createElement("style");
|
|
319
|
+
css.appendChild(
|
|
320
|
+
document.createTextNode(
|
|
321
|
+
"*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}",
|
|
322
|
+
),
|
|
323
|
+
);
|
|
324
|
+
document.head.appendChild(css);
|
|
325
|
+
|
|
326
|
+
return () => {
|
|
327
|
+
// Force restyle
|
|
328
|
+
(() => window.getComputedStyle(document.body))();
|
|
329
|
+
|
|
330
|
+
// Wait for next tick before removing
|
|
331
|
+
setTimeout(() => {
|
|
332
|
+
document.head.removeChild(css);
|
|
333
|
+
}, 1);
|
|
334
|
+
};
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const getSystemTheme = (e?: MediaQueryList | MediaQueryListEvent) => {
|
|
338
|
+
const event = e ?? window.matchMedia(MEDIA);
|
|
339
|
+
const isDark = event.matches;
|
|
340
|
+
const systemTheme = isDark ? "dark" : "light";
|
|
341
|
+
return systemTheme;
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
/*
|
|
345
|
+
This file is adapted from next-themes to work with tanstack start.
|
|
346
|
+
next-themes can be found at https://github.com/pacocoursey/next-themes under the MIT license.
|
|
347
|
+
*/
|
|
348
|
+
|
|
349
|
+
// biome-ignore lint/suspicious/noExplicitAny: Code is copied from the library
|
|
350
|
+
export const script: (...args: any[]) => void = (
|
|
351
|
+
attribute,
|
|
352
|
+
storageKey,
|
|
353
|
+
defaultTheme,
|
|
354
|
+
forcedTheme,
|
|
355
|
+
themes,
|
|
356
|
+
value,
|
|
357
|
+
enableSystem,
|
|
358
|
+
enableColorScheme,
|
|
359
|
+
) => {
|
|
360
|
+
const el = document.documentElement;
|
|
361
|
+
const systemThemes = ["light", "dark"];
|
|
362
|
+
const isClass = attribute === "class";
|
|
363
|
+
const classes =
|
|
364
|
+
isClass && value
|
|
365
|
+
? themes.map((t: string | number) => value[t] || t)
|
|
366
|
+
: themes;
|
|
367
|
+
|
|
368
|
+
function updateDOM(theme: string) {
|
|
369
|
+
if (isClass) {
|
|
370
|
+
el.classList.remove(...classes);
|
|
371
|
+
el.classList.add(theme);
|
|
372
|
+
} else {
|
|
373
|
+
el.setAttribute(attribute, theme);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
setColorScheme(theme);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function setColorScheme(theme: string) {
|
|
380
|
+
if (enableColorScheme && systemThemes.includes(theme)) {
|
|
381
|
+
el.style.colorScheme = theme;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function getSystemTheme() {
|
|
386
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
387
|
+
? "dark"
|
|
388
|
+
: "light";
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (forcedTheme) {
|
|
392
|
+
updateDOM(forcedTheme);
|
|
393
|
+
} else {
|
|
394
|
+
try {
|
|
395
|
+
const themeName = localStorage.getItem(storageKey) || defaultTheme;
|
|
396
|
+
const isSystem = enableSystem && themeName === "system";
|
|
397
|
+
const theme = isSystem ? getSystemTheme() : themeName;
|
|
398
|
+
updateDOM(theme);
|
|
399
|
+
} catch {
|
|
400
|
+
//
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
|
|
4
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils/css";
|
|
7
|
+
|
|
8
|
+
function Accordion(props: AccordionPrimitive.Root.Props) {
|
|
9
|
+
return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
|
|
13
|
+
return (
|
|
14
|
+
<AccordionPrimitive.Item
|
|
15
|
+
className={cn("border-b last:border-b-0", className)}
|
|
16
|
+
data-slot="accordion-item"
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function AccordionTrigger({
|
|
23
|
+
className,
|
|
24
|
+
children,
|
|
25
|
+
...props
|
|
26
|
+
}: AccordionPrimitive.Trigger.Props) {
|
|
27
|
+
return (
|
|
28
|
+
<AccordionPrimitive.Header className="flex">
|
|
29
|
+
<AccordionPrimitive.Trigger
|
|
30
|
+
className={cn(
|
|
31
|
+
"flex flex-1 cursor-pointer items-start justify-between gap-4 rounded-md py-4 text-left font-medium text-sm outline-none transition-all focus-visible:ring-[3px] focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-64 data-panel-open:*:data-[slot=accordion-indicator]:rotate-180",
|
|
32
|
+
className,
|
|
33
|
+
)}
|
|
34
|
+
data-slot="accordion-trigger"
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
{children}
|
|
38
|
+
<ChevronDownIcon
|
|
39
|
+
className="pointer-events-none size-4 shrink-0 translate-y-0.5 opacity-80 transition-transform duration-200 ease-in-out"
|
|
40
|
+
data-slot="accordion-indicator"
|
|
41
|
+
/>
|
|
42
|
+
</AccordionPrimitive.Trigger>
|
|
43
|
+
</AccordionPrimitive.Header>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function AccordionPanel({
|
|
48
|
+
className,
|
|
49
|
+
children,
|
|
50
|
+
...props
|
|
51
|
+
}: AccordionPrimitive.Panel.Props) {
|
|
52
|
+
return (
|
|
53
|
+
<AccordionPrimitive.Panel
|
|
54
|
+
className="h-(--accordion-panel-height) overflow-hidden text-muted-foreground text-sm transition-[height] duration-200 ease-in-out data-ending-style:h-0 data-starting-style:h-0"
|
|
55
|
+
data-slot="accordion-panel"
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
|
59
|
+
</AccordionPrimitive.Panel>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
Accordion,
|
|
65
|
+
AccordionItem,
|
|
66
|
+
AccordionTrigger,
|
|
67
|
+
AccordionPanel,
|
|
68
|
+
AccordionPanel as AccordionContent,
|
|
69
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils/css";
|
|
6
|
+
|
|
7
|
+
const AlertDialogCreateHandle = AlertDialogPrimitive.createHandle;
|
|
8
|
+
|
|
9
|
+
const AlertDialog = AlertDialogPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
12
|
+
|
|
13
|
+
function AlertDialogTrigger(props: AlertDialogPrimitive.Trigger.Props) {
|
|
14
|
+
return (
|
|
15
|
+
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function AlertDialogBackdrop({
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}: AlertDialogPrimitive.Backdrop.Props) {
|
|
23
|
+
return (
|
|
24
|
+
<AlertDialogPrimitive.Backdrop
|
|
25
|
+
className={cn(
|
|
26
|
+
"fixed inset-0 z-50 bg-black/32 backdrop-blur-sm transition-all duration-200 ease-out data-ending-style:opacity-0 data-starting-style:opacity-0",
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
data-slot="alert-dialog-backdrop"
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function AlertDialogViewport({
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: AlertDialogPrimitive.Viewport.Props) {
|
|
39
|
+
return (
|
|
40
|
+
<AlertDialogPrimitive.Viewport
|
|
41
|
+
className={cn(
|
|
42
|
+
"fixed inset-0 z-50 grid grid-rows-[1fr_auto_3fr] justify-items-center p-4",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
data-slot="alert-dialog-viewport"
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function AlertDialogPopup({
|
|
52
|
+
className,
|
|
53
|
+
bottomStickOnMobile = true,
|
|
54
|
+
...props
|
|
55
|
+
}: AlertDialogPrimitive.Popup.Props & {
|
|
56
|
+
bottomStickOnMobile?: boolean;
|
|
57
|
+
}) {
|
|
58
|
+
return (
|
|
59
|
+
<AlertDialogPortal>
|
|
60
|
+
<AlertDialogBackdrop />
|
|
61
|
+
<AlertDialogViewport
|
|
62
|
+
className={cn(
|
|
63
|
+
bottomStickOnMobile &&
|
|
64
|
+
"max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12",
|
|
65
|
+
)}
|
|
66
|
+
>
|
|
67
|
+
<AlertDialogPrimitive.Popup
|
|
68
|
+
className={cn(
|
|
69
|
+
"-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
70
|
+
bottomStickOnMobile &&
|
|
71
|
+
"max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden max-sm:before:rounded-none",
|
|
72
|
+
className,
|
|
73
|
+
)}
|
|
74
|
+
data-slot="alert-dialog-popup"
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
</AlertDialogViewport>
|
|
78
|
+
</AlertDialogPortal>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function AlertDialogHeader({
|
|
83
|
+
className,
|
|
84
|
+
...props
|
|
85
|
+
}: React.ComponentProps<"div">) {
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
className={cn(
|
|
89
|
+
"flex flex-col gap-2 p-6 text-center max-sm:pb-4 sm:text-left",
|
|
90
|
+
className,
|
|
91
|
+
)}
|
|
92
|
+
data-slot="alert-dialog-header"
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function AlertDialogFooter({
|
|
99
|
+
className,
|
|
100
|
+
variant = "default",
|
|
101
|
+
...props
|
|
102
|
+
}: React.ComponentProps<"div"> & {
|
|
103
|
+
variant?: "default" | "bare";
|
|
104
|
+
}) {
|
|
105
|
+
return (
|
|
106
|
+
<div
|
|
107
|
+
className={cn(
|
|
108
|
+
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]",
|
|
109
|
+
variant === "default" && "border-t bg-muted/72 py-4",
|
|
110
|
+
variant === "bare" && "pb-6",
|
|
111
|
+
className,
|
|
112
|
+
)}
|
|
113
|
+
data-slot="alert-dialog-footer"
|
|
114
|
+
{...props}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function AlertDialogTitle({
|
|
120
|
+
className,
|
|
121
|
+
...props
|
|
122
|
+
}: AlertDialogPrimitive.Title.Props) {
|
|
123
|
+
return (
|
|
124
|
+
<AlertDialogPrimitive.Title
|
|
125
|
+
className={cn(
|
|
126
|
+
"font-heading font-semibold text-xl leading-none",
|
|
127
|
+
className,
|
|
128
|
+
)}
|
|
129
|
+
data-slot="alert-dialog-title"
|
|
130
|
+
{...props}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function AlertDialogDescription({
|
|
136
|
+
className,
|
|
137
|
+
...props
|
|
138
|
+
}: AlertDialogPrimitive.Description.Props) {
|
|
139
|
+
return (
|
|
140
|
+
<AlertDialogPrimitive.Description
|
|
141
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
142
|
+
data-slot="alert-dialog-description"
|
|
143
|
+
{...props}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function AlertDialogClose(props: AlertDialogPrimitive.Close.Props) {
|
|
149
|
+
return (
|
|
150
|
+
<AlertDialogPrimitive.Close data-slot="alert-dialog-close" {...props} />
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
AlertDialogCreateHandle,
|
|
156
|
+
AlertDialog,
|
|
157
|
+
AlertDialogPortal,
|
|
158
|
+
AlertDialogBackdrop,
|
|
159
|
+
AlertDialogBackdrop as AlertDialogOverlay,
|
|
160
|
+
AlertDialogTrigger,
|
|
161
|
+
AlertDialogPopup,
|
|
162
|
+
AlertDialogPopup as AlertDialogContent,
|
|
163
|
+
AlertDialogHeader,
|
|
164
|
+
AlertDialogFooter,
|
|
165
|
+
AlertDialogTitle,
|
|
166
|
+
AlertDialogDescription,
|
|
167
|
+
AlertDialogClose,
|
|
168
|
+
AlertDialogViewport,
|
|
169
|
+
};
|