@ramme-io/ui 4.1.0 → 4.1.1
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/README.md +4 -3
- package/dist/component-registry.js +55 -52
- package/dist/components/ai/AIChatThread/AIChatThread.js +3 -3
- package/dist/components/ai/NewsSummaryCard/NewsSummaryCard.js +17 -17
- package/dist/components/ai/StockChart/StockChart.js +4 -4
- package/dist/components/auth/LoginPage.d.ts +22 -0
- package/dist/components/auth/LoginPage.js +50 -42
- package/dist/components/forms/ComboBox.js +2 -2
- package/dist/components/forms/DatePicker.js +37 -32
- package/dist/components/forms/FileUpload.js +39 -37
- package/dist/components/forms/Input.js +19 -18
- package/dist/components/forms/MultiSelect.js +9 -8
- package/dist/components/forms/Select.js +9 -8
- package/dist/components/forms/Textarea.d.ts +13 -11
- package/dist/components/forms/Textarea.js +36 -16
- package/dist/components/layout/Accordion.js +25 -32
- package/dist/components/layout/Card.js +38 -21
- package/dist/components/layout/DetailDrawer.js +36 -37
- package/dist/components/layout/SettingsContainer.js +23 -13
- package/dist/components/layout/Sheet.d.ts +58 -0
- package/dist/components/layout/Sheet.js +144 -0
- package/dist/components/navigation/MobileNav.d.ts +44 -1
- package/dist/components/navigation/MobileNav.js +96 -70
- package/dist/components/navigation/Tabs.js +19 -12
- package/dist/components/ui/icon-loader.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +218 -211
- package/dist/lib/hooks/useSheetGesture.d.ts +81 -0
- package/dist/lib/hooks/useSheetGesture.js +70 -0
- package/dist/setupTests.d.ts +1 -0
- package/dist/wizardManifest.js +130 -10
- package/package.json +9 -2
- package/src/wizardManifest.ts +130 -10
package/README.md
CHANGED
|
@@ -225,7 +225,7 @@ Props, variants and live examples are in Storybook (`pnpm run storybook`) and at
|
|
|
225
225
|
| `MenuDivider` | `@atom/primitive/menu-divider` | A visual separator for grouping MenuItems within a Menu. |
|
|
226
226
|
| `MenuItem` | `@atom/primitive/menu-item` | An individual selectable item within a Menu component. |
|
|
227
227
|
| `Message` | `@molecule/ai/message` | Displays a single message in a conversation, including an avatar, author, content, and optional suggestions. |
|
|
228
|
-
| `MobileNav` | `@molecule/nav/mobile-nav` |
|
|
228
|
+
| `MobileNav` | `@molecule/nav/mobile-nav` | Mobile navigation, in two shapes. |
|
|
229
229
|
| `MultiSelect` | `@molecule/form/multi-select` | A searchable dropdown for picking several options at once, rendering selections as removable chips. |
|
|
230
230
|
| `NewsSummaryCard` | `@molecule/ai/news-summary-card` | AI-generated news summary card with recent headlines |
|
|
231
231
|
| `PageHeader` | `@atom/templates-patterns/page-header` | Displays the main header section of a page, including a title, optional description, and a slot for action buttons. |
|
|
@@ -253,7 +253,7 @@ Props, variants and live examples are in Storybook (`pnpm run storybook`) and at
|
|
|
253
253
|
| `Tabs` | `@molecule/nav/tabs` | A navigation component that allows users to switch between different content panels within the same area. |
|
|
254
254
|
| `TelemetryGraph` | `@molecule/ai/telemetry-graph` | AI-generated telemetry visualization component |
|
|
255
255
|
| `TelemetryLog` | `@molecule/iot/telemetry-log` | A scrolling, newest-first table of raw sensor readings with a bounded row count. |
|
|
256
|
-
| `Textarea` | `@atom/form/textarea` | A theme-aware
|
|
256
|
+
| `Textarea` | `@atom/form/textarea` | A theme-aware multi-line text input with label, helper text, and validation state support. |
|
|
257
257
|
| `TippyTooltip` | `@molecule/feedback/tippy-tooltip` | A flexible and theme-aware tooltip component that displays additional information on hover. |
|
|
258
258
|
| `Toast` | `@molecule/feedback/toast` | A single, transient notification message that appears briefly to provide feedback. |
|
|
259
259
|
| `ToastProvider` | `@molecule/feedback/toast-provider` | Provides a context for displaying transient notifications (toasts). |
|
|
@@ -262,7 +262,7 @@ Props, variants and live examples are in Storybook (`pnpm run storybook`) and at
|
|
|
262
262
|
| `WatchlistEngine` | `@molecule/block/watchlist-engine` | A self-contained financial watchlist showing tickers with live price, day change, market cap, and a risk grade. |
|
|
263
263
|
| `WaterPumpControl` | `@molecule/iot/water-pump-control` | An irrigation control block: choose automatic or manual operation and set the soil-moisture target the controller should hold. |
|
|
264
264
|
|
|
265
|
-
### Layouts (
|
|
265
|
+
### Layouts (33)
|
|
266
266
|
|
|
267
267
|
| Name | SKU | What it is |
|
|
268
268
|
| --- | --- | --- |
|
|
@@ -294,6 +294,7 @@ Props, variants and live examples are in Storybook (`pnpm run storybook`) and at
|
|
|
294
294
|
| `Modal` | `@chassis/layout/modal` | A centered dialog that blocks interaction with the page until dismissed. |
|
|
295
295
|
| `PageContainer` | `@chassis/layout/page-container` | Standard responsive padding wrapper for the content inside a page. |
|
|
296
296
|
| `SettingsContainer` | `@chassis/layout/settings-container` | The canonical settings page arrangement, with a fixed slot per section so every app's settings read the same way. |
|
|
297
|
+
| `Sheet` | `@chassis/layout/sheet` | A bottom sheet that opens at a partial height and grows to full screen as you drag or scroll it up. |
|
|
297
298
|
| `Sidebar` | `@chassis/layout/sidebar` | A collapsible, theme-aware application navigation rail. |
|
|
298
299
|
| `Statusbar` | `@chassis/layout/statusbar` | The persistent strip pinned to the bottom of the app shell. |
|
|
299
300
|
| `Toolbar` | `@chassis/layout/toolbar` | The secondary action strip that sits beneath the header. |
|
|
@@ -22,8 +22,8 @@ import { AuthLayout as g } from "./components/auth/AuthLayout.js";
|
|
|
22
22
|
import { LoginPage as b } from "./components/auth/LoginPage.js";
|
|
23
23
|
import { SignupPage as C } from "./components/auth/SignupPage.js";
|
|
24
24
|
import { ActivityFeed as y } from "./components/data-display/ActivityFeed.js";
|
|
25
|
-
import { AreaChart as
|
|
26
|
-
import { BarChart as
|
|
25
|
+
import { AreaChart as S } from "./components/data-display/AreaChart.js";
|
|
26
|
+
import { BarChart as v } from "./components/data-display/BarChart.js";
|
|
27
27
|
import { ChartWithTable as T } from "./components/data-display/ChartWithTable.js";
|
|
28
28
|
import { CodeBlock as D } from "./components/data-display/CodeBlock.js";
|
|
29
29
|
import { DataTable as A } from "./components/data-display/DataTable.js";
|
|
@@ -77,25 +77,26 @@ import { PageContainer as dr } from "./components/layout/PageContainer.js";
|
|
|
77
77
|
import { PageHeader as lr } from "./components/layout/PageHeader.js";
|
|
78
78
|
import { SectionHeader as fr } from "./components/layout/SectionHeader.js";
|
|
79
79
|
import { SettingsContainer as sr } from "./components/layout/SettingsContainer.js";
|
|
80
|
-
import {
|
|
81
|
-
import {
|
|
82
|
-
import {
|
|
80
|
+
import { Sheet as zr } from "./components/layout/Sheet.js";
|
|
81
|
+
import { Sidebar as Jr } from "./components/layout/Sidebar.js";
|
|
82
|
+
import { Statusbar as Vr } from "./components/layout/Statusbar.js";
|
|
83
|
+
import { Toolbar as Xr } from "./components/layout/Toolbar.js";
|
|
83
84
|
import { ButtonItem as ur, UserNav as hr } from "./components/layout/UserNav.js";
|
|
84
85
|
import { ConnectorOverlay as gr } from "./components/molecular/ConnectorOverlay.js";
|
|
85
86
|
import { DataCard as br } from "./components/molecular/DataCard.js";
|
|
86
87
|
import { StateMatrix as Cr } from "./components/molecular/StateMatrix.js";
|
|
87
|
-
import { Breadcrumbs as
|
|
88
|
-
import { Menu as
|
|
88
|
+
import { Breadcrumbs as Zr, BreadcrumbItem as yr } from "./components/navigation/Breadcrumbs.js";
|
|
89
|
+
import { Menu as $r, MenuItem as Sr, MenuDivider as vr } from "./components/navigation/Menu.js";
|
|
89
90
|
import { MobileNav as Tr } from "./components/navigation/MobileNav.js";
|
|
90
|
-
import { Pagination as
|
|
91
|
-
import { Stepper as
|
|
92
|
-
import { Tabs as
|
|
93
|
-
import { Avatar as
|
|
94
|
-
import { Badge as
|
|
91
|
+
import { Pagination as rt } from "./components/navigation/Pagination.js";
|
|
92
|
+
import { Stepper as tt } from "./components/navigation/Stepper.js";
|
|
93
|
+
import { Tabs as et, TabPanel as Dr } from "./components/navigation/Tabs.js";
|
|
94
|
+
import { Avatar as ot } from "./components/ui/Avatar.js";
|
|
95
|
+
import { Badge as at } from "./components/ui/Badge.js";
|
|
95
96
|
import { BrandLogo as Ar } from "./components/ui/BrandLogo.js";
|
|
96
|
-
import { Button as
|
|
97
|
-
import { Icon as
|
|
98
|
-
const
|
|
97
|
+
import { Button as it } from "./components/ui/Button.js";
|
|
98
|
+
import { Icon as mt } from "./components/ui/Icon.js";
|
|
99
|
+
const Xe = {
|
|
99
100
|
Suggestion: Pr,
|
|
100
101
|
suggestion: Pr,
|
|
101
102
|
Actions: Br,
|
|
@@ -166,12 +167,12 @@ const Je = {
|
|
|
166
167
|
ActivityFeed: y,
|
|
167
168
|
"activity-feed": y,
|
|
168
169
|
activityfeed: y,
|
|
169
|
-
AreaChart:
|
|
170
|
-
"area-chart":
|
|
171
|
-
areachart:
|
|
172
|
-
BarChart:
|
|
173
|
-
"bar-chart":
|
|
174
|
-
barchart:
|
|
170
|
+
AreaChart: S,
|
|
171
|
+
"area-chart": S,
|
|
172
|
+
areachart: S,
|
|
173
|
+
BarChart: v,
|
|
174
|
+
"bar-chart": v,
|
|
175
|
+
barchart: v,
|
|
175
176
|
ChartWithTable: T,
|
|
176
177
|
"chart-with-table": T,
|
|
177
178
|
chartwithtable: T,
|
|
@@ -346,12 +347,14 @@ const Je = {
|
|
|
346
347
|
SettingsContainer: sr,
|
|
347
348
|
"settings-container": sr,
|
|
348
349
|
settingscontainer: sr,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
350
|
+
Sheet: zr,
|
|
351
|
+
sheet: zr,
|
|
352
|
+
Sidebar: Jr,
|
|
353
|
+
sidebar: Jr,
|
|
354
|
+
Statusbar: Vr,
|
|
355
|
+
statusbar: Vr,
|
|
356
|
+
Toolbar: Xr,
|
|
357
|
+
toolbar: Xr,
|
|
355
358
|
UserNav: hr,
|
|
356
359
|
"user-nav": hr,
|
|
357
360
|
usernav: hr,
|
|
@@ -370,40 +373,40 @@ const Je = {
|
|
|
370
373
|
BreadcrumbItem: yr,
|
|
371
374
|
"breadcrumb-item": yr,
|
|
372
375
|
breadcrumbitem: yr,
|
|
373
|
-
Breadcrumbs:
|
|
374
|
-
breadcrumbs:
|
|
375
|
-
MenuDivider:
|
|
376
|
-
"menu-divider":
|
|
377
|
-
menudivider:
|
|
378
|
-
MenuItem:
|
|
379
|
-
"menu-item":
|
|
380
|
-
menuitem:
|
|
381
|
-
Menu:
|
|
382
|
-
menu:
|
|
376
|
+
Breadcrumbs: Zr,
|
|
377
|
+
breadcrumbs: Zr,
|
|
378
|
+
MenuDivider: vr,
|
|
379
|
+
"menu-divider": vr,
|
|
380
|
+
menudivider: vr,
|
|
381
|
+
MenuItem: Sr,
|
|
382
|
+
"menu-item": Sr,
|
|
383
|
+
menuitem: Sr,
|
|
384
|
+
Menu: $r,
|
|
385
|
+
menu: $r,
|
|
383
386
|
MobileNav: Tr,
|
|
384
387
|
"mobile-nav": Tr,
|
|
385
388
|
mobilenav: Tr,
|
|
386
|
-
Pagination:
|
|
387
|
-
pagination:
|
|
388
|
-
Stepper:
|
|
389
|
-
stepper:
|
|
389
|
+
Pagination: rt,
|
|
390
|
+
pagination: rt,
|
|
391
|
+
Stepper: tt,
|
|
392
|
+
stepper: tt,
|
|
390
393
|
TabPanel: Dr,
|
|
391
394
|
"tab-panel": Dr,
|
|
392
395
|
tabpanel: Dr,
|
|
393
|
-
Tabs:
|
|
394
|
-
tabs:
|
|
395
|
-
Avatar:
|
|
396
|
-
avatar:
|
|
397
|
-
Badge:
|
|
398
|
-
badge:
|
|
396
|
+
Tabs: et,
|
|
397
|
+
tabs: et,
|
|
398
|
+
Avatar: ot,
|
|
399
|
+
avatar: ot,
|
|
400
|
+
Badge: at,
|
|
401
|
+
badge: at,
|
|
399
402
|
BrandLogo: Ar,
|
|
400
403
|
"brand-logo": Ar,
|
|
401
404
|
brandlogo: Ar,
|
|
402
|
-
Button:
|
|
403
|
-
button:
|
|
404
|
-
Icon:
|
|
405
|
-
icon:
|
|
405
|
+
Button: it,
|
|
406
|
+
button: it,
|
|
407
|
+
Icon: mt,
|
|
408
|
+
icon: mt
|
|
406
409
|
};
|
|
407
410
|
export {
|
|
408
|
-
|
|
411
|
+
Xe as AUTO_REGISTRY
|
|
409
412
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as c, jsx as t, Fragment as w } from "react/jsx-runtime";
|
|
2
|
-
import { useState as
|
|
2
|
+
import { useState as B, useRef as R, useEffect as D, useCallback as N } from "react";
|
|
3
3
|
import { CodeBlock as G } from "../../data-display/CodeBlock.js";
|
|
4
4
|
import { Icon as C } from "../../ui/Icon.js";
|
|
5
5
|
import { PromptInput as $ } from "../../../blocks/ai/PromptInput.js";
|
|
@@ -91,12 +91,12 @@ const W = () => /* @__PURE__ */ t("div", { className: "flex items-center gap-1 p
|
|
|
91
91
|
activeModel: i,
|
|
92
92
|
connectionStatus: d,
|
|
93
93
|
renderMessage: u,
|
|
94
|
-
placeholder: f = "Ask
|
|
94
|
+
placeholder: f = "Ask AI…",
|
|
95
95
|
className: h,
|
|
96
96
|
suggestions: s,
|
|
97
97
|
onSuggestionClick: k
|
|
98
98
|
}) => {
|
|
99
|
-
const _ = d ?? (a ? "error" : l ? "streaming" : "idle"), [b, y] =
|
|
99
|
+
const _ = d ?? (a ? "error" : l ? "streaming" : "idle"), [b, y] = B(""), v = R(null);
|
|
100
100
|
D(() => {
|
|
101
101
|
var r;
|
|
102
102
|
(r = v.current) == null || r.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
import { jsxs as t, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import { useState as i, useEffect as g } from "react";
|
|
3
3
|
import { Card as N, CardHeader as b, CardTitle as w, CardContent as y } from "../../layout/Card.js";
|
|
4
|
-
import { Icon as
|
|
4
|
+
import { Icon as s } from "../../ui/Icon.js";
|
|
5
5
|
const d = { BASE_URL: "/", DEV: !1, MODE: "production", PROD: !0, SSR: !1 }, k = ({ params: u }) => {
|
|
6
|
-
const { ticker:
|
|
6
|
+
const { ticker: a } = u, [c, x] = i([]), [l, m] = i(!0), [n, p] = i(null);
|
|
7
7
|
return g(() => {
|
|
8
8
|
(async () => {
|
|
9
9
|
try {
|
|
10
10
|
m(!0), p(null);
|
|
11
|
-
const
|
|
11
|
+
const o = (d == null ? void 0 : d.VITE_API_URL) ?? "http://localhost:8000", f = await fetch(`${o}/companies/${a.toUpperCase()}/news?limit=5`);
|
|
12
12
|
if (!f.ok)
|
|
13
|
-
throw new Error(`No news available for ${
|
|
13
|
+
throw new Error(`No news available for ${a.toUpperCase()}`);
|
|
14
14
|
const h = await f.json();
|
|
15
15
|
x(h);
|
|
16
|
-
} catch (
|
|
17
|
-
p(
|
|
16
|
+
} catch (o) {
|
|
17
|
+
p(o instanceof Error ? o.message : "Failed to fetch news");
|
|
18
18
|
} finally {
|
|
19
19
|
m(!1);
|
|
20
20
|
}
|
|
21
21
|
})();
|
|
22
|
-
}, [
|
|
22
|
+
}, [a]), /* @__PURE__ */ t(N, { className: "w-full min-w-[320px] max-w-2xl shadow-lg border-primary/20", children: [
|
|
23
23
|
/* @__PURE__ */ e(b, { className: "pb-3", children: /* @__PURE__ */ t(w, { className: "text-sm font-medium text-muted-foreground flex items-center gap-2", children: [
|
|
24
|
-
/* @__PURE__ */ e(
|
|
24
|
+
/* @__PURE__ */ e(s, { name: "newspaper", size: 14 }),
|
|
25
25
|
"Recent News · ",
|
|
26
|
-
|
|
26
|
+
a.toUpperCase()
|
|
27
27
|
] }) }),
|
|
28
28
|
/* @__PURE__ */ t(y, { className: "pt-0", children: [
|
|
29
|
-
l && /* @__PURE__ */ e("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ e(
|
|
30
|
-
|
|
31
|
-
/* @__PURE__ */ e(
|
|
32
|
-
/* @__PURE__ */ e("span", { children:
|
|
29
|
+
l && /* @__PURE__ */ e("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ e(s, { name: "loader", size: 24, className: "animate-spin text-muted-foreground" }) }),
|
|
30
|
+
n && /* @__PURE__ */ t("div", { className: "flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [
|
|
31
|
+
/* @__PURE__ */ e(s, { name: "alert-circle", size: 14, className: "mt-px shrink-0" }),
|
|
32
|
+
/* @__PURE__ */ e("span", { children: n })
|
|
33
33
|
] }),
|
|
34
|
-
c.length === 0 && !l && !
|
|
35
|
-
/* @__PURE__ */ e(
|
|
34
|
+
c.length === 0 && !l && !n && /* @__PURE__ */ t("div", { className: "flex flex-col items-center justify-center py-8 gap-2 text-muted-foreground", children: [
|
|
35
|
+
/* @__PURE__ */ e(s, { name: "inbox", size: 24, opacity: 0.5 }),
|
|
36
36
|
/* @__PURE__ */ e("p", { className: "text-sm", children: "No recent news available" })
|
|
37
37
|
] }),
|
|
38
|
-
c.length > 0 && !l && !
|
|
38
|
+
c.length > 0 && !l && !n && /* @__PURE__ */ e("div", { className: "space-y-3", children: c.map((r) => /* @__PURE__ */ e(
|
|
39
39
|
"div",
|
|
40
40
|
{
|
|
41
41
|
className: "border-b border-border/50 pb-3 last:border-0 last:pb-0",
|
|
@@ -64,7 +64,7 @@ const d = { BASE_URL: "/", DEV: !1, MODE: "production", PROD: !0, SSR: !1 }, k =
|
|
|
64
64
|
] })
|
|
65
65
|
] })
|
|
66
66
|
] }),
|
|
67
|
-
r.url && /* @__PURE__ */ e(
|
|
67
|
+
r.url && /* @__PURE__ */ e(s, { name: "external-link", size: 12, className: "text-muted-foreground/50 flex-shrink-0 mt-0.5" })
|
|
68
68
|
] })
|
|
69
69
|
},
|
|
70
70
|
r.id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as a, jsx as e } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import { ResponsiveContainer as
|
|
2
|
+
import _ from "react";
|
|
3
|
+
import { ResponsiveContainer as F, ComposedChart as W, CartesianGrid as K, XAxis as U, YAxis as A, Tooltip as $, Legend as j, Line as S, Bar as z } from "recharts";
|
|
4
4
|
import { Card as E, CardHeader as H, CardTitle as L, CardContent as V } from "../../layout/Card.js";
|
|
5
5
|
import { useChartTheme as Y } from "../../../lib/hooks/useChartTheme.js";
|
|
6
6
|
function G(s, p, C) {
|
|
@@ -59,7 +59,7 @@ const b = {
|
|
|
59
59
|
data: C
|
|
60
60
|
}) => {
|
|
61
61
|
var y, k;
|
|
62
|
-
const { ticker: N, timeRange: M, metrics: c } = s, { textColor: g, gridColor: l } = Y(), h = N || s.symbol || "UNKNOWN", r = M || "1M", o = c && Array.isArray(c) && c.length > 0 ? c : ["price", "volume"], x =
|
|
62
|
+
const { ticker: N, timeRange: M, metrics: c } = s, { textColor: g, gridColor: l } = Y(), h = N || s.symbol || "UNKNOWN", r = M || "1M", o = c && Array.isArray(c) && c.length > 0 ? c : ["price", "volume"], x = _.useMemo(
|
|
63
63
|
() => {
|
|
64
64
|
const t = C || G(r, o);
|
|
65
65
|
return console.log("[StockChart] Data generated:", {
|
|
@@ -98,7 +98,7 @@ const b = {
|
|
|
98
98
|
] })
|
|
99
99
|
] }) }),
|
|
100
100
|
/* @__PURE__ */ a(V, { className: "pt-0", children: [
|
|
101
|
-
/* @__PURE__ */ e("div", { className: "h-64 w-full bg-background", style: { minHeight: "256px", minWidth: "350px" }, children: /* @__PURE__ */ e(
|
|
101
|
+
/* @__PURE__ */ e("div", { className: "h-64 w-full bg-background", style: { minHeight: "256px", minWidth: "350px" }, children: /* @__PURE__ */ e(F, { width: "100%", height: 256, children: /* @__PURE__ */ a(W, { data: x, margin: { top: 5, right: 20, bottom: 5, left: 0 }, children: [
|
|
102
102
|
/* @__PURE__ */ e(K, { strokeDasharray: "3 3", stroke: l, opacity: 0.3 }),
|
|
103
103
|
/* @__PURE__ */ e(
|
|
104
104
|
U,
|
|
@@ -10,6 +10,9 @@ import React from 'react';
|
|
|
10
10
|
* @param {string} error - Message shown above the form when sign-in fails.
|
|
11
11
|
* @param {boolean} loading - Disables the form and shows progress while authenticating.
|
|
12
12
|
* @param {QuickProfile[]} quickProfiles - Optional one-click demo identities, each `{ name, email, role }`.
|
|
13
|
+
* @param {string} signupHref - Where "Create one" points. Pass `null` to hide that line entirely, which is what an invite-only product wants. Defaults to `/auth/signup`.
|
|
14
|
+
* @param {string} signupLabel - Text for that link. Defaults to "Create one".
|
|
15
|
+
* @param {string} forgotHref - Where "Forgot?" points. Pass `null` to hide it — a product with no reset email has nothing to link to. Defaults to `#`.
|
|
13
16
|
*/
|
|
14
17
|
export interface QuickProfile {
|
|
15
18
|
name: string;
|
|
@@ -21,5 +24,24 @@ export interface LoginPageProps {
|
|
|
21
24
|
error?: string | null;
|
|
22
25
|
loading?: boolean;
|
|
23
26
|
quickProfiles?: QuickProfile[];
|
|
27
|
+
/**
|
|
28
|
+
* Where "Create one" goes, or `null` to hide the line.
|
|
29
|
+
*
|
|
30
|
+
* Defaults to `/auth/signup` so every product that already renders this keeps
|
|
31
|
+
* exactly what it has. Invite-only products pass `null`: ramme.io deleted its
|
|
32
|
+
* signup route when accounts became invite-only, and this link kept pointing at
|
|
33
|
+
* it — a dead end offered to everyone who could not get in.
|
|
34
|
+
*/
|
|
35
|
+
signupHref?: string | null;
|
|
36
|
+
signupLabel?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Where "Forgot?" goes, or `null` to hide it.
|
|
39
|
+
*
|
|
40
|
+
* Defaults to `#`, which is what it has always been — a link that does nothing.
|
|
41
|
+
* Worth being able to remove: on a product with no reset email, offering a
|
|
42
|
+
* recovery link that goes nowhere is worse than saying so in plain words
|
|
43
|
+
* underneath the form.
|
|
44
|
+
*/
|
|
45
|
+
forgotHref?: string | null;
|
|
24
46
|
}
|
|
25
47
|
export declare const LoginPage: React.FC<LoginPageProps>;
|
|
@@ -1,98 +1,106 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { Link as
|
|
4
|
-
import { Button as
|
|
5
|
-
import { Input as
|
|
6
|
-
import { Alert as
|
|
1
|
+
import { jsxs as a, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useState as h } from "react";
|
|
3
|
+
import { Link as x } from "react-router-dom";
|
|
4
|
+
import { Button as v } from "../ui/Button.js";
|
|
5
|
+
import { Input as f } from "../forms/Input.js";
|
|
6
|
+
import { Alert as y } from "../feedback/Alert.js";
|
|
7
7
|
import { Icon as s } from "../ui/Icon.js";
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const A = ({
|
|
9
|
+
onLogin: g,
|
|
10
|
+
error: l,
|
|
11
|
+
loading: i,
|
|
12
|
+
quickProfiles: r,
|
|
13
|
+
signupHref: n = "/auth/signup",
|
|
14
|
+
signupLabel: b = "Create one",
|
|
15
|
+
forgotHref: o = "#"
|
|
16
|
+
}) => {
|
|
17
|
+
const [c, d] = h(""), [m, u] = h(""), N = (t) => {
|
|
18
|
+
t.preventDefault(), g(c, m);
|
|
19
|
+
}, p = "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 mb-2 block text-foreground/90";
|
|
20
|
+
return /* @__PURE__ */ a("div", { className: "w-full max-w-[400px] space-y-6 animate-in fade-in zoom-in-95 duration-300", children: [
|
|
21
|
+
/* @__PURE__ */ a("div", { className: "flex flex-col items-center space-y-2 text-center mb-8", children: [
|
|
14
22
|
/* @__PURE__ */ e("div", { className: "h-10 w-10 bg-primary/10 rounded-xl flex items-center justify-center mb-2 border border-primary/20", children: /* @__PURE__ */ e(s, { name: "hexagon", className: "text-primary fill-primary/20", size: 24, strokeWidth: 2.5 }) }),
|
|
15
23
|
/* @__PURE__ */ e("h1", { className: "text-2xl font-bold tracking-tight", children: "Welcome back" }),
|
|
16
24
|
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "Enter your credentials to access your workspace" })
|
|
17
25
|
] }),
|
|
18
|
-
/* @__PURE__ */
|
|
19
|
-
/* @__PURE__ */ e("div", { className: "p-6 pt-6", children: /* @__PURE__ */
|
|
20
|
-
l && /* @__PURE__ */ e(
|
|
21
|
-
/* @__PURE__ */
|
|
22
|
-
/* @__PURE__ */ e("label", { htmlFor: "email", className:
|
|
23
|
-
/* @__PURE__ */
|
|
26
|
+
/* @__PURE__ */ a("div", { className: "bg-card text-card-foreground border shadow-sm rounded-xl overflow-hidden", children: [
|
|
27
|
+
/* @__PURE__ */ e("div", { className: "p-6 pt-6", children: /* @__PURE__ */ a("form", { onSubmit: N, className: "space-y-4", children: [
|
|
28
|
+
l && /* @__PURE__ */ e(y, { variant: "danger", title: "Authentication Error", className: "mb-4", children: l }),
|
|
29
|
+
/* @__PURE__ */ a("div", { className: "space-y-1", children: [
|
|
30
|
+
/* @__PURE__ */ e("label", { htmlFor: "email", className: p, children: "Email" }),
|
|
31
|
+
/* @__PURE__ */ a("div", { className: "relative group", children: [
|
|
24
32
|
/* @__PURE__ */ e(s, { name: "mail", className: "absolute left-3 top-2.5 h-4 w-4 text-muted-foreground group-focus-within:text-primary transition-colors" }),
|
|
25
33
|
/* @__PURE__ */ e(
|
|
26
|
-
|
|
34
|
+
f,
|
|
27
35
|
{
|
|
28
36
|
id: "email",
|
|
29
37
|
type: "email",
|
|
30
38
|
placeholder: "name@example.com",
|
|
31
39
|
className: "pl-9 h-10 bg-background/50",
|
|
32
|
-
value:
|
|
33
|
-
onChange: (
|
|
40
|
+
value: c,
|
|
41
|
+
onChange: (t) => d(t.target.value),
|
|
34
42
|
required: !0
|
|
35
43
|
}
|
|
36
44
|
)
|
|
37
45
|
] })
|
|
38
46
|
] }),
|
|
39
|
-
/* @__PURE__ */
|
|
40
|
-
/* @__PURE__ */
|
|
41
|
-
/* @__PURE__ */ e("label", { htmlFor: "password", className:
|
|
42
|
-
/* @__PURE__ */ e(
|
|
47
|
+
/* @__PURE__ */ a("div", { className: "space-y-1", children: [
|
|
48
|
+
/* @__PURE__ */ a("div", { className: "flex items-center justify-between", children: [
|
|
49
|
+
/* @__PURE__ */ e("label", { htmlFor: "password", className: p, children: "Password" }),
|
|
50
|
+
o !== null && /* @__PURE__ */ e(x, { to: o, className: "text-xs text-primary hover:underline font-medium", children: "Forgot?" })
|
|
43
51
|
] }),
|
|
44
|
-
/* @__PURE__ */
|
|
52
|
+
/* @__PURE__ */ a("div", { className: "relative group", children: [
|
|
45
53
|
/* @__PURE__ */ e(s, { name: "lock", className: "absolute left-3 top-2.5 h-4 w-4 text-muted-foreground group-focus-within:text-primary transition-colors" }),
|
|
46
54
|
/* @__PURE__ */ e(
|
|
47
|
-
|
|
55
|
+
f,
|
|
48
56
|
{
|
|
49
57
|
id: "password",
|
|
50
58
|
type: "password",
|
|
51
59
|
className: "pl-9 h-10 bg-background/50",
|
|
52
|
-
value:
|
|
53
|
-
onChange: (
|
|
60
|
+
value: m,
|
|
61
|
+
onChange: (t) => u(t.target.value),
|
|
54
62
|
required: !0
|
|
55
63
|
}
|
|
56
64
|
)
|
|
57
65
|
] })
|
|
58
66
|
] }),
|
|
59
|
-
/* @__PURE__ */ e(
|
|
67
|
+
/* @__PURE__ */ e(v, { type: "submit", className: "w-full mt-2", size: "lg", disabled: i, children: i ? "Authenticating..." : "Sign In" })
|
|
60
68
|
] }) }),
|
|
61
|
-
r && r.length > 0 && /* @__PURE__ */
|
|
62
|
-
/* @__PURE__ */
|
|
69
|
+
r && r.length > 0 && /* @__PURE__ */ a("div", { className: "px-6 pb-6 space-y-3", children: [
|
|
70
|
+
/* @__PURE__ */ a("div", { className: "relative mb-4", children: [
|
|
63
71
|
/* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ e("span", { className: "w-full border-t border-border/50" }) }),
|
|
64
72
|
/* @__PURE__ */ e("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ e("span", { className: "bg-card px-2 text-muted-foreground", children: "Quick Select Profiles" }) })
|
|
65
73
|
] }),
|
|
66
|
-
/* @__PURE__ */ e("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: r.map((
|
|
74
|
+
/* @__PURE__ */ e("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: r.map((t) => /* @__PURE__ */ a(
|
|
67
75
|
"button",
|
|
68
76
|
{
|
|
69
77
|
type: "button",
|
|
70
78
|
onClick: () => {
|
|
71
|
-
|
|
79
|
+
d(t.email), u("demo");
|
|
72
80
|
},
|
|
73
81
|
className: "flex flex-col items-start p-3 text-left border rounded-lg hover:border-primary hover:bg-primary/5 transition-all w-full focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 focus:ring-offset-card",
|
|
74
82
|
children: [
|
|
75
|
-
/* @__PURE__ */ e("span", { className: "font-medium text-sm text-foreground", children:
|
|
76
|
-
/* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children:
|
|
83
|
+
/* @__PURE__ */ e("span", { className: "font-medium text-sm text-foreground", children: t.name }),
|
|
84
|
+
/* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children: t.role })
|
|
77
85
|
]
|
|
78
86
|
},
|
|
79
|
-
|
|
87
|
+
t.email
|
|
80
88
|
)) })
|
|
81
89
|
] }),
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
/* @__PURE__ */
|
|
90
|
+
n !== null && /* @__PURE__ */ a("div", { className: "p-6 pt-0 text-center", children: [
|
|
91
|
+
/* @__PURE__ */ a("div", { className: "relative mb-4", children: [
|
|
84
92
|
/* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ e("span", { className: "w-full border-t" }) }),
|
|
85
93
|
/* @__PURE__ */ e("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ e("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with" }) })
|
|
86
94
|
] }),
|
|
87
|
-
/* @__PURE__ */
|
|
95
|
+
/* @__PURE__ */ a("p", { className: "text-sm text-muted-foreground", children: [
|
|
88
96
|
"Don't have an account?",
|
|
89
97
|
" ",
|
|
90
|
-
/* @__PURE__ */ e(
|
|
98
|
+
/* @__PURE__ */ e(x, { to: n, className: "font-semibold text-primary hover:underline transition-all", children: b })
|
|
91
99
|
] })
|
|
92
100
|
] })
|
|
93
101
|
] })
|
|
94
102
|
] });
|
|
95
103
|
};
|
|
96
104
|
export {
|
|
97
|
-
|
|
105
|
+
A as LoginPage
|
|
98
106
|
};
|
|
@@ -2,7 +2,7 @@ import { jsxs as D, jsx as i } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState as l, useRef as g, useEffect as f, useCallback as K } from "react";
|
|
3
3
|
import { Input as q } from "./Input.js";
|
|
4
4
|
import { cn as p } from "../../utils/cn.js";
|
|
5
|
-
const
|
|
5
|
+
const _ = ({
|
|
6
6
|
options: t,
|
|
7
7
|
label: v,
|
|
8
8
|
value: a,
|
|
@@ -73,5 +73,5 @@ const $ = ({
|
|
|
73
73
|
] });
|
|
74
74
|
};
|
|
75
75
|
export {
|
|
76
|
-
|
|
76
|
+
_ as ComboBox
|
|
77
77
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
1
|
+
import { jsxs as d, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import s from "react";
|
|
3
|
+
import b from "react-datepicker";
|
|
3
4
|
import { cn as e } from "../../utils/cn.js";
|
|
4
|
-
import { Icon as
|
|
5
|
+
import { Icon as u } from "../ui/Icon.js";
|
|
5
6
|
import "react-datepicker/dist/react-datepicker.css";
|
|
6
|
-
const
|
|
7
|
+
const f = `
|
|
7
8
|
.react-datepicker {
|
|
8
9
|
font-family: inherit !important;
|
|
9
10
|
background-color: rgb(var(--app-card-bg-color)) !important;
|
|
@@ -28,36 +29,40 @@ const m = `
|
|
|
28
29
|
.react-datepicker__navigation-icon::before {
|
|
29
30
|
border-color: rgb(var(--app-text-color)) !important;
|
|
30
31
|
}
|
|
31
|
-
`,
|
|
32
|
+
`, y = ({
|
|
32
33
|
label: o,
|
|
33
|
-
selected:
|
|
34
|
-
onChange:
|
|
35
|
-
className:
|
|
34
|
+
selected: l,
|
|
35
|
+
onChange: n,
|
|
36
|
+
className: p,
|
|
36
37
|
error: t,
|
|
37
38
|
helperText: a,
|
|
38
|
-
...
|
|
39
|
-
}) =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
/* @__PURE__ */ r(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
39
|
+
...c
|
|
40
|
+
}) => {
|
|
41
|
+
const m = s.useId(), i = c.id || m;
|
|
42
|
+
return /* @__PURE__ */ d("div", { className: e("w-full flex flex-col", p), children: [
|
|
43
|
+
/* @__PURE__ */ r("style", { children: f }),
|
|
44
|
+
o && /* @__PURE__ */ r("label", { htmlFor: i, className: "block text-sm font-medium text-foreground mb-1.5", children: o }),
|
|
45
|
+
/* @__PURE__ */ d("div", { className: "relative", children: [
|
|
46
|
+
/* @__PURE__ */ r(
|
|
47
|
+
b,
|
|
48
|
+
{
|
|
49
|
+
id: i,
|
|
50
|
+
selected: l,
|
|
51
|
+
onChange: n,
|
|
52
|
+
className: e(
|
|
53
|
+
"flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
54
|
+
t ? "border-destructive" : "border-input"
|
|
55
|
+
),
|
|
56
|
+
wrapperClassName: "w-full",
|
|
57
|
+
showPopperArrow: !1,
|
|
58
|
+
...c
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
/* @__PURE__ */ r("div", { className: "absolute right-3 top-2.5 pointer-events-none text-muted-foreground", children: /* @__PURE__ */ r(u, { name: "calendar", className: "h-4 w-4" }) })
|
|
62
|
+
] }),
|
|
63
|
+
a && /* @__PURE__ */ r("p", { className: e("mt-1.5 text-xs", t ? "text-destructive" : "text-muted-foreground"), children: a })
|
|
64
|
+
] });
|
|
65
|
+
};
|
|
61
66
|
export {
|
|
62
|
-
|
|
67
|
+
y as DatePicker
|
|
63
68
|
};
|