@ramme-io/ui 4.1.0 → 4.2.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/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 +35 -35
- package/dist/components/auth/LoginPage.d.ts +22 -0
- package/dist/components/auth/LoginPage.js +50 -42
- package/dist/components/data-display/StatusBadge.d.ts +4 -3
- package/dist/components/data-display/StatusBadge.js +18 -18
- package/dist/components/feedback/Alert.js +19 -19
- 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/SegmentedControl.js +10 -10
- 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.d.ts +9 -1
- package/dist/components/layout/DetailDrawer.js +60 -51
- package/dist/components/layout/Drawer.js +47 -39
- package/dist/components/layout/Modal.js +28 -23
- package/dist/components/layout/SettingsContainer.js +23 -13
- package/dist/components/layout/Sheet.d.ts +58 -0
- package/dist/components/layout/Sheet.js +146 -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.css +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +218 -209
- package/dist/lib/hooks/useDialogFocus.d.ts +1 -0
- package/dist/lib/hooks/useDialogFocus.js +46 -0
- 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 +139 -14
- package/package.json +9 -2
- package/src/wizardManifest.ts +139 -14
- package/tailwind.preset.js +8 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gesture behind a bottom sheet.
|
|
3
|
+
*
|
|
4
|
+
* This is the library's first pointer-driven interaction. Nothing else in
|
|
5
|
+
* @ramme-io/ui uses Pointer Events at all — every interactive component is an
|
|
6
|
+
* HTML form element — so the rules it establishes are worth stating once:
|
|
7
|
+
*
|
|
8
|
+
* - **Pointer Events only.** One code path for touch, mouse, pen and trackpad.
|
|
9
|
+
* Separate `mousemove` and `touchmove` handlers are how you end up with a
|
|
10
|
+
* control that works on one and jitters on the other.
|
|
11
|
+
* - **`setPointerCapture`.** A drag must survive the finger leaving the
|
|
12
|
+
* element. Without capture, dragging a sheet up past its own top edge stops
|
|
13
|
+
* tracking, which reads as the sheet sticking.
|
|
14
|
+
* - **`touch-action: none`** on the drag surface, applied by the component.
|
|
15
|
+
* Without it the browser claims the gesture for scrolling and the sheet
|
|
16
|
+
* never moves.
|
|
17
|
+
*
|
|
18
|
+
* WHY THE SETTLE MATH IS A PURE FUNCTION
|
|
19
|
+
*
|
|
20
|
+
* jsdom has no layout and cannot drag, so the only honest way to test a gesture
|
|
21
|
+
* is to make its decisions independent of the DOM. `settleTo` below takes
|
|
22
|
+
* numbers and returns a number; every interesting rule — flick beats position,
|
|
23
|
+
* dragging below the smallest detent dismisses, a slow drag snaps to nearest —
|
|
24
|
+
* is checkable without a browser.
|
|
25
|
+
*/
|
|
26
|
+
/** Pixels per millisecond past which a drag counts as a flick rather than a move. */
|
|
27
|
+
export declare const FLICK_VELOCITY = 0.5;
|
|
28
|
+
/**
|
|
29
|
+
* How far below the smallest detent the sheet must be dragged before release
|
|
30
|
+
* dismisses it. Expressed as a fraction of the viewport so it scales with the
|
|
31
|
+
* screen rather than being generous on a tablet and twitchy on a phone.
|
|
32
|
+
*/
|
|
33
|
+
export declare const DISMISS_THRESHOLD = 0.12;
|
|
34
|
+
export interface SettleInput {
|
|
35
|
+
/** Current height of the sheet as a fraction of the viewport, 0–1. */
|
|
36
|
+
current: number;
|
|
37
|
+
/** Allowed resting heights, ascending fractions of the viewport. */
|
|
38
|
+
detents: number[];
|
|
39
|
+
/**
|
|
40
|
+
* Vertical velocity in px/ms. NEGATIVE is upward (the sheet growing), matching
|
|
41
|
+
* pointer coordinates where y decreases toward the top of the screen.
|
|
42
|
+
*/
|
|
43
|
+
velocity: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Where the sheet should come to rest when the finger lifts.
|
|
47
|
+
*
|
|
48
|
+
* Returns the target detent, or `null` meaning "dismiss".
|
|
49
|
+
*
|
|
50
|
+
* Order matters: a flick is honoured before position, because a fast downward
|
|
51
|
+
* flick from near the top should close the sheet rather than snap it to the
|
|
52
|
+
* detent it happens to be nearest. That is what every native sheet does, and
|
|
53
|
+
* getting it backwards makes the sheet feel like it is fighting you.
|
|
54
|
+
*/
|
|
55
|
+
export declare function settleTo({ current, detents, velocity }: SettleInput): number | null;
|
|
56
|
+
export interface SheetGestureOptions {
|
|
57
|
+
detents: number[];
|
|
58
|
+
initialDetent?: number;
|
|
59
|
+
onDismiss: () => void;
|
|
60
|
+
/** Skips the drag entirely; the sheet still opens and closes, just without motion. */
|
|
61
|
+
reducedMotion?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface SheetGesture {
|
|
64
|
+
/** Current height as a fraction of the viewport. */
|
|
65
|
+
height: number;
|
|
66
|
+
/** True while a finger is down — the component uses this to drop its transition. */
|
|
67
|
+
dragging: boolean;
|
|
68
|
+
/** True when the sheet is at its tallest detent. */
|
|
69
|
+
expanded: boolean;
|
|
70
|
+
/** Attach to the grabber and header. */
|
|
71
|
+
onPointerDown: (e: React.PointerEvent) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Attach to the scrollable body. Implements the behaviour the pattern is
|
|
74
|
+
* named for: at a partial detent, dragging up grows the sheet instead of
|
|
75
|
+
* scrolling; once expanded, the content scrolls normally; and at the top of
|
|
76
|
+
* the content, dragging down shrinks the sheet again.
|
|
77
|
+
*/
|
|
78
|
+
onBodyPointerDown: (e: React.PointerEvent) => void;
|
|
79
|
+
setHeight: (h: number) => void;
|
|
80
|
+
}
|
|
81
|
+
export declare function useSheetGesture({ detents, initialDetent, onDismiss, reducedMotion, }: SheetGestureOptions): SheetGesture;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useState as M, useRef as u, useCallback as T, useEffect as C } from "react";
|
|
2
|
+
const D = 0.5, P = 0.12;
|
|
3
|
+
function y({ current: l, detents: f, velocity: a }) {
|
|
4
|
+
if (!f.length) return null;
|
|
5
|
+
const s = [...f].sort((r, e) => r - e), n = s[0], c = s[s.length - 1];
|
|
6
|
+
if (Math.abs(a) >= D) {
|
|
7
|
+
if (a > 0) {
|
|
8
|
+
const e = s.filter((g) => g < l - 0.01);
|
|
9
|
+
return e.length ? e[e.length - 1] : null;
|
|
10
|
+
}
|
|
11
|
+
const r = s.filter((e) => e > l + 0.01);
|
|
12
|
+
return r.length ? r[0] : c;
|
|
13
|
+
}
|
|
14
|
+
return l < n - P ? null : s.reduce(
|
|
15
|
+
(r, e) => Math.abs(e - l) < Math.abs(r - l) ? e : r
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function R({
|
|
19
|
+
detents: l,
|
|
20
|
+
initialDetent: f = 0,
|
|
21
|
+
onDismiss: a,
|
|
22
|
+
reducedMotion: s = !1
|
|
23
|
+
}) {
|
|
24
|
+
const n = [...l].sort((t, i) => t - i), [c, r] = M(n[f] ?? n[0]), [e, g] = M(!1), L = u(0), S = u(0), w = u(0), v = u(0), E = u(0), d = u(null), h = T(
|
|
25
|
+
(t, i) => {
|
|
26
|
+
if (!s && t.isPrimary) {
|
|
27
|
+
if (d.current = i ? t.currentTarget : null, i) {
|
|
28
|
+
const o = t.currentTarget.scrollTop <= 0;
|
|
29
|
+
if (c >= n[n.length - 1] - 1e-3 && !o) return;
|
|
30
|
+
}
|
|
31
|
+
L.current = t.clientY, w.current = t.clientY, v.current = t.timeStamp, S.current = c, E.current = 0, g(!0), t.currentTarget.setPointerCapture(t.pointerId);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
[c, s, n]
|
|
35
|
+
), b = T((t) => h(t, !1), [h]), H = T((t) => h(t, !0), [h]);
|
|
36
|
+
return C(() => {
|
|
37
|
+
if (!e) return;
|
|
38
|
+
const t = (o) => {
|
|
39
|
+
const Y = window.innerHeight || 1, I = o.clientY - L.current, x = o.timeStamp - v.current;
|
|
40
|
+
x > 0 && (E.current = (o.clientY - w.current) / x), w.current = o.clientY, v.current = o.timeStamp;
|
|
41
|
+
let p = S.current - I / Y;
|
|
42
|
+
const m = n[n.length - 1];
|
|
43
|
+
p > m && (p = m + (p - m) * 0.25), r(Math.max(0, Math.min(p, m + 0.05))), d.current && (d.current.scrollTop = 0);
|
|
44
|
+
}, i = () => {
|
|
45
|
+
g(!1);
|
|
46
|
+
const o = y({
|
|
47
|
+
current: c,
|
|
48
|
+
detents: n,
|
|
49
|
+
velocity: E.current
|
|
50
|
+
});
|
|
51
|
+
o === null ? a() : r(o), d.current = null;
|
|
52
|
+
};
|
|
53
|
+
return window.addEventListener("pointermove", t), window.addEventListener("pointerup", i), window.addEventListener("pointercancel", i), () => {
|
|
54
|
+
window.removeEventListener("pointermove", t), window.removeEventListener("pointerup", i), window.removeEventListener("pointercancel", i);
|
|
55
|
+
};
|
|
56
|
+
}, [e, c, a, n]), {
|
|
57
|
+
height: c,
|
|
58
|
+
dragging: e,
|
|
59
|
+
expanded: c >= n[n.length - 1] - 1e-3,
|
|
60
|
+
onPointerDown: b,
|
|
61
|
+
onBodyPointerDown: H,
|
|
62
|
+
setHeight: r
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
P as DISMISS_THRESHOLD,
|
|
67
|
+
D as FLICK_VELOCITY,
|
|
68
|
+
y as settleTo,
|
|
69
|
+
R as useSheetGesture
|
|
70
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
package/dist/wizardManifest.js
CHANGED
|
@@ -596,7 +596,7 @@ const e = {
|
|
|
596
596
|
{
|
|
597
597
|
id: "login-page",
|
|
598
598
|
name: "LoginPage",
|
|
599
|
-
version: "1.0.
|
|
599
|
+
version: "1.0.1",
|
|
600
600
|
description: "The standard sign-in screen — email and password, with inline error and loading states already wired. Strategic purpose: a drop-in credential form so products don't rebuild one; `quickProfiles` adds one-click demo personas, which is what makes a prototype instantly explorable without real accounts.",
|
|
601
601
|
tags: [
|
|
602
602
|
"auth",
|
|
@@ -626,6 +626,21 @@ const e = {
|
|
|
626
626
|
name: "quickProfiles",
|
|
627
627
|
type: "Array<QuickProfile>",
|
|
628
628
|
description: "Optional one-click demo identities, each `{ name, email, role }`."
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
name: "signupHref",
|
|
632
|
+
type: "string",
|
|
633
|
+
description: 'Where "Create one" points. Pass `null` to hide that line entirely, which is what an invite-only product wants. Defaults to `/auth/signup`.'
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
name: "signupLabel",
|
|
637
|
+
type: "string",
|
|
638
|
+
description: 'Text for that link. Defaults to "Create one".'
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
name: "forgotHref",
|
|
642
|
+
type: "string",
|
|
643
|
+
description: 'Where "Forgot?" points. Pass `null` to hide it — a product with no reset email has nothing to link to. Defaults to `#`.'
|
|
629
644
|
}
|
|
630
645
|
],
|
|
631
646
|
importPath: "./components/auth/LoginPage",
|
|
@@ -1083,7 +1098,7 @@ const e = {
|
|
|
1083
1098
|
{
|
|
1084
1099
|
id: "status-badge",
|
|
1085
1100
|
name: "StatusBadge",
|
|
1086
|
-
version: "1.0.
|
|
1101
|
+
version: "1.0.2",
|
|
1087
1102
|
description: "A consistent status indicator featuring a color-coded dot and an optional text label. Essential for IoT devices and system states.",
|
|
1088
1103
|
tags: [
|
|
1089
1104
|
"status",
|
|
@@ -1102,7 +1117,7 @@ const e = {
|
|
|
1102
1117
|
{
|
|
1103
1118
|
name: "color",
|
|
1104
1119
|
type: "string",
|
|
1105
|
-
description: "
|
|
1120
|
+
description: "Background class for the dot (e.g. 'bg-success'). Use a semantic token — a numeric shade does not adapt to the active theme. Overrides the `status` preset's colour when both are given."
|
|
1106
1121
|
},
|
|
1107
1122
|
{
|
|
1108
1123
|
name: "label",
|
|
@@ -1961,31 +1976,53 @@ const e = {
|
|
|
1961
1976
|
{
|
|
1962
1977
|
id: "textarea",
|
|
1963
1978
|
name: "Textarea",
|
|
1964
|
-
version: "1.0.
|
|
1965
|
-
description: "A theme-aware
|
|
1979
|
+
version: "1.0.1",
|
|
1980
|
+
description: "A theme-aware multi-line text input with label, helper text, and validation state support. Strategic purpose: the multi-line sibling of Input, styled identically so the two are indistinguishable when stacked in one form. Forwards all standard HTML textarea attributes via spread.",
|
|
1966
1981
|
tags: [
|
|
1967
1982
|
"form",
|
|
1968
1983
|
"input",
|
|
1969
|
-
"ui"
|
|
1984
|
+
"ui",
|
|
1985
|
+
"text",
|
|
1986
|
+
"multiline"
|
|
1970
1987
|
],
|
|
1971
1988
|
category: "form",
|
|
1972
1989
|
props: [
|
|
1973
1990
|
{
|
|
1974
1991
|
name: "label",
|
|
1975
1992
|
type: "string",
|
|
1976
|
-
description: "
|
|
1993
|
+
description: "Optional label displayed above the textarea."
|
|
1994
|
+
},
|
|
1995
|
+
{
|
|
1996
|
+
name: "helperText",
|
|
1997
|
+
type: "string",
|
|
1998
|
+
description: "Supporting text rendered below the textarea. Appears in destructive color when error is true."
|
|
1999
|
+
},
|
|
2000
|
+
{
|
|
2001
|
+
name: "error",
|
|
2002
|
+
type: "boolean",
|
|
2003
|
+
description: "If true, applies destructive border styling to indicate a validation error. Defaults to false."
|
|
2004
|
+
},
|
|
2005
|
+
{
|
|
2006
|
+
name: "required",
|
|
2007
|
+
type: "boolean",
|
|
2008
|
+
description: "If true, appends a required (*) indicator next to the label. Defaults to false."
|
|
2009
|
+
},
|
|
2010
|
+
{
|
|
2011
|
+
name: "showOptionalLabel",
|
|
2012
|
+
type: "boolean",
|
|
2013
|
+
description: "If true, appends an (optional) label when the field is not required. Defaults to false."
|
|
1977
2014
|
},
|
|
1978
2015
|
{
|
|
1979
2016
|
name: "containerClassName",
|
|
1980
2017
|
type: "string",
|
|
1981
|
-
description: "
|
|
2018
|
+
description: "Additional CSS classes applied to the outer container div."
|
|
1982
2019
|
}
|
|
1983
2020
|
],
|
|
1984
2021
|
importPath: "./components/forms/Textarea",
|
|
1985
2022
|
filePath: "src/components/forms/Textarea.tsx",
|
|
1986
2023
|
sku: "@atom/form/textarea",
|
|
1987
2024
|
humanLabel: "Textarea",
|
|
1988
|
-
humanDescription: "A theme-aware
|
|
2025
|
+
humanDescription: "A theme-aware multi-line text input with label, helper text, and validation state support. Strategic purpose: the multi-line sibling of Input, styled identically so the two are indistinguishable when stacked in one form. Forwards all standard HTML textarea attributes via spread."
|
|
1989
2026
|
},
|
|
1990
2027
|
{
|
|
1991
2028
|
id: "toggle-switch",
|
|
@@ -2619,8 +2656,8 @@ const e = {
|
|
|
2619
2656
|
{
|
|
2620
2657
|
id: "mobile-nav",
|
|
2621
2658
|
name: "MobileNav",
|
|
2622
|
-
version: "1.0.
|
|
2623
|
-
description:
|
|
2659
|
+
version: "1.0.3",
|
|
2660
|
+
description: `Mobile navigation, in two shapes. 'bar' is a fixed bottom tab bar with icon+label tabs and a "More" drawer for secondary links. 'sheet' drops the bar entirely and puts every destination in a bottom drawer the host opens from its own trigger — the right choice when a mobile browser's toolbar already owns the bottom edge. Hidden on md: and up via Tailwind. The mobile counterpart to the desktop Sidebar.`,
|
|
2624
2661
|
tags: [
|
|
2625
2662
|
"navigation",
|
|
2626
2663
|
"mobile",
|
|
@@ -2669,13 +2706,33 @@ const e = {
|
|
|
2669
2706
|
name: "className",
|
|
2670
2707
|
type: "string",
|
|
2671
2708
|
description: "Additional CSS classes on the root nav bar."
|
|
2709
|
+
},
|
|
2710
|
+
{
|
|
2711
|
+
name: "variant",
|
|
2712
|
+
type: "string",
|
|
2713
|
+
description: `'bar' (default) renders the fixed bottom tab bar with a "More" Drawer. 'sheet' renders no bar at all and puts every destination in a Sheet — opening at 60% and growing to full as you drag or scroll it up — which the host opens itself — use it when a top header can hold the trigger, since a fixed bar and a mobile browser's own toolbar stack into ~120px of lost screen.`
|
|
2714
|
+
},
|
|
2715
|
+
{
|
|
2716
|
+
name: "isOpen",
|
|
2717
|
+
type: "boolean",
|
|
2718
|
+
description: "Controlled drawer state. Required by 'sheet', which has no trigger of its own; ignored by 'bar'."
|
|
2719
|
+
},
|
|
2720
|
+
{
|
|
2721
|
+
name: "onOpenChange",
|
|
2722
|
+
type: "function",
|
|
2723
|
+
description: "Fired when the sheet wants to close (backdrop, Escape, or an item tapped)."
|
|
2724
|
+
},
|
|
2725
|
+
{
|
|
2726
|
+
name: "children",
|
|
2727
|
+
type: "ReactNode",
|
|
2728
|
+
description: "Extra content rendered in the panel body after the destinations, scrolling with them. The mirror of drawerHeader; use it instead of drawerFooter when the content belongs with the list rather than pinned under it."
|
|
2672
2729
|
}
|
|
2673
2730
|
],
|
|
2674
2731
|
importPath: "./components/navigation/MobileNav",
|
|
2675
2732
|
filePath: "src/components/navigation/MobileNav.tsx",
|
|
2676
2733
|
sku: "@molecule/nav/mobile-nav",
|
|
2677
2734
|
humanLabel: "MobileNav",
|
|
2678
|
-
humanDescription:
|
|
2735
|
+
humanDescription: `Mobile navigation, in two shapes. 'bar' is a fixed bottom tab bar with icon+label tabs and a "More" drawer for secondary links. 'sheet' drops the bar entirely and puts every destination in a bottom drawer the host opens from its own trigger — the right choice when a mobile browser's toolbar already owns the bottom edge. Hidden on md: and up via Tailwind. The mobile counterpart to the desktop Sidebar.`
|
|
2679
2736
|
},
|
|
2680
2737
|
{
|
|
2681
2738
|
id: "pagination",
|
|
@@ -3614,7 +3671,7 @@ const e = {
|
|
|
3614
3671
|
{
|
|
3615
3672
|
id: "detail-drawer",
|
|
3616
3673
|
name: "DetailDrawer",
|
|
3617
|
-
version: "1.0.
|
|
3674
|
+
version: "1.0.2",
|
|
3618
3675
|
description: 'A resizable side panel for inspecting one record without leaving the list. Strategic purpose: the master-detail companion — `push` compresses its siblings in a flex layout so the list stays visible and usable, while `overlay` floats above the page like a classic drawer. Use this for "click a row, see the detail" flows; use Modal when the task must block everything else.',
|
|
3619
3676
|
tags: [
|
|
3620
3677
|
"layout",
|
|
@@ -3639,7 +3696,7 @@ const e = {
|
|
|
3639
3696
|
{
|
|
3640
3697
|
name: "variant",
|
|
3641
3698
|
type: "string",
|
|
3642
|
-
description: "'push' compresses sibling flex content so the list stays visible; 'overlay' floats fixed above the page. Defaults to
|
|
3699
|
+
description: "'push' compresses sibling flex content so the list stays visible; 'overlay' floats fixed above the page. Defaults to overlay."
|
|
3643
3700
|
},
|
|
3644
3701
|
{
|
|
3645
3702
|
name: "side",
|
|
@@ -3671,6 +3728,11 @@ const e = {
|
|
|
3671
3728
|
type: "number",
|
|
3672
3729
|
description: "Upper bound for resizing. Defaults to 60% of the window width."
|
|
3673
3730
|
},
|
|
3731
|
+
{
|
|
3732
|
+
name: "title",
|
|
3733
|
+
type: "string",
|
|
3734
|
+
description: 'Names the panel for assistive technology. Not rendered: there is no header row to put it in, and adding one is a design decision. Without it an overlay announces only as "dialog".'
|
|
3735
|
+
},
|
|
3674
3736
|
{
|
|
3675
3737
|
name: "children",
|
|
3676
3738
|
type: "ReactNode",
|
|
@@ -4086,6 +4148,69 @@ const e = {
|
|
|
4086
4148
|
humanLabel: "SettingsContainer",
|
|
4087
4149
|
humanDescription: "The canonical settings page arrangement, with a fixed slot per section so every app's settings read the same way. Strategic purpose: settings sprawl fast — this pins the section order and navigation so General, AI Gateway, Theme Lab, and About always live in the same place."
|
|
4088
4150
|
},
|
|
4151
|
+
{
|
|
4152
|
+
id: "sheet",
|
|
4153
|
+
name: "Sheet",
|
|
4154
|
+
version: "1.0.0",
|
|
4155
|
+
description: "A bottom sheet that opens at a partial height and grows to full screen as you drag or scroll it up. Strategic purpose: the native-feeling surface for mobile navigation, settings and pickers — reachable by thumb, dismissed by flicking down. Use instead of Drawer when the surface is primarily touched.",
|
|
4156
|
+
tags: [
|
|
4157
|
+
"layout",
|
|
4158
|
+
"overlay",
|
|
4159
|
+
"sheet",
|
|
4160
|
+
"mobile",
|
|
4161
|
+
"touch",
|
|
4162
|
+
"drawer",
|
|
4163
|
+
"ui"
|
|
4164
|
+
],
|
|
4165
|
+
category: "layout",
|
|
4166
|
+
props: [
|
|
4167
|
+
{
|
|
4168
|
+
name: "isOpen",
|
|
4169
|
+
type: "boolean",
|
|
4170
|
+
description: "Controls the open/closed state. Required."
|
|
4171
|
+
},
|
|
4172
|
+
{
|
|
4173
|
+
name: "onClose",
|
|
4174
|
+
type: "function",
|
|
4175
|
+
description: "Fired when the sheet requests dismissal (flick down, drag below the smallest detent, Escape, overlay tap, or the close button). Required."
|
|
4176
|
+
},
|
|
4177
|
+
{
|
|
4178
|
+
name: "detents",
|
|
4179
|
+
type: "Array<number>",
|
|
4180
|
+
description: "Resting heights as fractions of the viewport, ascending. Defaults to [0.6, 1] — opens at 60%, expands to full."
|
|
4181
|
+
},
|
|
4182
|
+
{
|
|
4183
|
+
name: "initialDetent",
|
|
4184
|
+
type: "number",
|
|
4185
|
+
description: "Index into detents to open at. Defaults to 0."
|
|
4186
|
+
},
|
|
4187
|
+
{
|
|
4188
|
+
name: "title",
|
|
4189
|
+
type: "string",
|
|
4190
|
+
description: "Optional title in the sticky header, beside the close button."
|
|
4191
|
+
},
|
|
4192
|
+
{
|
|
4193
|
+
name: "footer",
|
|
4194
|
+
type: "ReactNode",
|
|
4195
|
+
description: "Optional sticky footer, kept clear of the home indicator."
|
|
4196
|
+
},
|
|
4197
|
+
{
|
|
4198
|
+
name: "overlayDismiss",
|
|
4199
|
+
type: "boolean",
|
|
4200
|
+
description: "Tap the dimmed backdrop to close. Defaults to true."
|
|
4201
|
+
},
|
|
4202
|
+
{
|
|
4203
|
+
name: "className",
|
|
4204
|
+
type: "string",
|
|
4205
|
+
description: "Extra classes for the sheet panel."
|
|
4206
|
+
}
|
|
4207
|
+
],
|
|
4208
|
+
importPath: "./components/layout/Sheet",
|
|
4209
|
+
filePath: "src/components/layout/Sheet.tsx",
|
|
4210
|
+
sku: "@chassis/layout/sheet",
|
|
4211
|
+
humanLabel: "Sheet",
|
|
4212
|
+
humanDescription: "A bottom sheet that opens at a partial height and grows to full screen as you drag or scroll it up. Strategic purpose: the native-feeling surface for mobile navigation, settings and pickers — reachable by thumb, dismissed by flicking down. Use instead of Drawer when the surface is primarily touched."
|
|
4213
|
+
},
|
|
4089
4214
|
{
|
|
4090
4215
|
id: "sidebar",
|
|
4091
4216
|
name: "Sidebar",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ramme-io/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "The structural component library for the Ramme Framework.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -61,6 +61,8 @@
|
|
|
61
61
|
"@storybook/addon-themes": "^10.5.9",
|
|
62
62
|
"@storybook/react": "^10.5.9",
|
|
63
63
|
"@storybook/react-vite": "^10.5.9",
|
|
64
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
65
|
+
"@testing-library/react": "^16.3.2",
|
|
64
66
|
"@types/doctrine": "^0.0.9",
|
|
65
67
|
"@types/node": "^20.12.12",
|
|
66
68
|
"@types/react": "^18.3.23",
|
|
@@ -70,16 +72,21 @@
|
|
|
70
72
|
"ag-grid-community": "^31.3.2",
|
|
71
73
|
"ag-grid-react": "^31.3.2",
|
|
72
74
|
"autoprefixer": "^10.4.19",
|
|
75
|
+
"axe-core": "^4.13.0",
|
|
73
76
|
"doctrine": "^3.0.0",
|
|
77
|
+
"jsdom": "^29.0.0",
|
|
74
78
|
"postcss": "^8.4.38",
|
|
75
79
|
"storybook": "^10.5.9",
|
|
76
80
|
"tailwindcss": "^3.4.4",
|
|
77
81
|
"typescript": "^5.4.5",
|
|
78
82
|
"vite": "^5.3.1",
|
|
79
|
-
"vite-plugin-dts": "^3.9.1"
|
|
83
|
+
"vite-plugin-dts": "^3.9.1",
|
|
84
|
+
"vitest": "^2.1.9",
|
|
85
|
+
"vitest-axe": "^0.1.0"
|
|
80
86
|
},
|
|
81
87
|
"scripts": {
|
|
82
88
|
"dev": "vite",
|
|
89
|
+
"test": "vitest run",
|
|
83
90
|
"generate:manifest": "node scripts/generate-manifest.js",
|
|
84
91
|
"generate:registry": "node scripts/generate-registry.js",
|
|
85
92
|
"generate": "npm run generate:manifest && npm run generate:registry",
|