@astryxdesign/lab 0.1.9-canary.d2d84f8 → 0.1.9-canary.e00a241
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/BottomSheet/BottomSheet.d.ts +95 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheet.js +150 -0
- package/dist/BottomSheet/index.d.ts +9 -0
- package/dist/BottomSheet/index.d.ts.map +1 -0
- package/dist/BottomSheet/index.js +10 -0
- package/dist/BottomSheet/useSheetGestures.d.ts +69 -0
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -0
- package/dist/BottomSheet/useSheetGestures.js +163 -0
- package/dist/RichTextEditor/RichTextEditor.d.ts +67 -6
- package/dist/RichTextEditor/RichTextEditor.d.ts.map +1 -1
- package/dist/RichTextEditor/RichTextEditor.js +165 -12
- package/dist/RichTextEditor/editorTheme.d.ts.map +1 -1
- package/dist/RichTextEditor/editorTheme.js +33 -7
- package/dist/RichTextEditor/index.d.ts +1 -1
- package/dist/RichTextEditor/index.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/lab.css +23 -0
- package/package.json +2 -2
- package/src/BottomSheet/BottomSheet.doc.mjs +105 -0
- package/src/BottomSheet/BottomSheet.test.tsx +233 -0
- package/src/BottomSheet/BottomSheet.tsx +226 -0
- package/src/BottomSheet/index.ts +11 -0
- package/src/BottomSheet/useSheetGestures.doc.mjs +31 -0
- package/src/BottomSheet/useSheetGestures.test.ts +160 -0
- package/src/BottomSheet/useSheetGestures.ts +226 -0
- package/src/ChatReasoning/ChatReasoning.doc.mjs +49 -2
- package/src/CodeEditor/CodeEditor.doc.mjs +67 -2
- package/src/LogStream/LogStream.doc.mjs +53 -2
- package/src/RichTextEditor/RichTextEditor.doc.mjs +19 -1
- package/src/RichTextEditor/RichTextEditor.test.tsx +441 -11
- package/src/RichTextEditor/RichTextEditor.tsx +289 -31
- package/src/RichTextEditor/editorTheme.ts +63 -3
- package/src/RichTextEditor/index.ts +2 -0
- package/src/Schedule/Schedule.doc.mjs +143 -3
- package/src/Stepper/Stepper.doc.mjs +6 -0
- package/src/__tests__/labApiContractDrift.test.tsx +57 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file BottomSheet.tsx
|
|
3
|
+
* @input Uses React, StyleX, theme tokens, Drawer, useSheetGestures, themeProps
|
|
4
|
+
* @output Exports BottomSheet component and BottomSheetProps
|
|
5
|
+
* @position Lab implementation; consumed by index.ts, tested by BottomSheet.test.tsx, demonstrated in Storybook
|
|
6
|
+
*
|
|
7
|
+
* A mobile touch surface that rises from the bottom edge with a grab handle
|
|
8
|
+
* and swipe-to-dismiss. Built ON TOP OF the lab Drawer's native `<dialog>`
|
|
9
|
+
* engine (`side="bottom"`) rather than forking it — Drawer owns
|
|
10
|
+
* showModal/show, the open/close slide animation, focus trap + restore,
|
|
11
|
+
* scroll lock, the Escape/scrim contract, and the LIFO overlay registry.
|
|
12
|
+
* BottomSheet layers the grab handle and the drag-to-dismiss gesture on top,
|
|
13
|
+
* inside the dialog.
|
|
14
|
+
*
|
|
15
|
+
* The gesture translate is applied to an inner sheet wrapper, not the
|
|
16
|
+
* `<dialog>` itself, so Drawer owns the open/close slide and the drag
|
|
17
|
+
* translates within it without the two transforms fighting.
|
|
18
|
+
*
|
|
19
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
20
|
+
* - /packages/lab/src/BottomSheet/BottomSheet.doc.mjs (props table, features, usage)
|
|
21
|
+
* - /packages/lab/src/BottomSheet/BottomSheet.test.tsx (tests for new/changed behavior)
|
|
22
|
+
* - /packages/lab/src/BottomSheet/index.ts (exports if types change)
|
|
23
|
+
* - /apps/storybook/stories/BottomSheet.stories.tsx (examples and visual coverage)
|
|
24
|
+
*/
|
|
25
|
+
import { type ReactNode } from 'react';
|
|
26
|
+
import type { BaseProps } from '@astryxdesign/core';
|
|
27
|
+
/**
|
|
28
|
+
* Height budget for each named size. `medium`/`tall` track the viewport so
|
|
29
|
+
* the sheet scales with the device; `short` is a fixed peek height. `auto`
|
|
30
|
+
* is handled separately (fits content, capped at the `tall` budget).
|
|
31
|
+
*/
|
|
32
|
+
declare const HEIGHT_BUDGETS: {
|
|
33
|
+
readonly short: "240px";
|
|
34
|
+
readonly medium: "50dvh";
|
|
35
|
+
readonly tall: "90dvh";
|
|
36
|
+
readonly auto: "90dvh";
|
|
37
|
+
};
|
|
38
|
+
export type BottomSheetHeight = keyof typeof HEIGHT_BUDGETS;
|
|
39
|
+
export interface BottomSheetProps extends BaseProps<HTMLDialogElement> {
|
|
40
|
+
/** Ref forwarded to the underlying <dialog> element. */
|
|
41
|
+
ref?: React.Ref<HTMLDialogElement>;
|
|
42
|
+
/** Whether the sheet is open. Fully controlled — pair with `onOpenChange`. */
|
|
43
|
+
isOpen: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Called when the sheet opens or closes. The boolean is the requested
|
|
46
|
+
* next state (`false` on Escape, scrim click, or a swipe past the dismiss
|
|
47
|
+
* threshold). The caller owns the open state.
|
|
48
|
+
*/
|
|
49
|
+
onOpenChange: (isOpen: boolean) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Accessible label for the sheet (required — the sheet has no built-in
|
|
52
|
+
* heading to derive a name from).
|
|
53
|
+
*/
|
|
54
|
+
label: string;
|
|
55
|
+
/** Sheet content, rendered below the grab handle in a scrollable area. */
|
|
56
|
+
children: ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* How tall the sheet is:
|
|
59
|
+
* - `'short'` — a fixed peek height
|
|
60
|
+
* - `'medium'` — half the viewport
|
|
61
|
+
* - `'tall'` — nearly the full viewport
|
|
62
|
+
* - `'auto'` — fits its content, capped at the `'tall'` budget
|
|
63
|
+
*
|
|
64
|
+
* On viewports shorter than the budget the sheet fills the available
|
|
65
|
+
* height.
|
|
66
|
+
* @default 'medium'
|
|
67
|
+
*/
|
|
68
|
+
height?: BottomSheetHeight;
|
|
69
|
+
/** Test ID for the root element. */
|
|
70
|
+
'data-testid'?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A mobile touch sheet that rises from the bottom edge, with a grab handle
|
|
74
|
+
* and swipe-to-dismiss. Built on the lab Drawer's `<dialog>` engine
|
|
75
|
+
* (`side="bottom"`): Drawer owns the open/close slide, focus trap + restore,
|
|
76
|
+
* scroll lock, and the Escape/scrim contract, while BottomSheet layers the
|
|
77
|
+
* grab handle and drag-to-dismiss on top.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```
|
|
81
|
+
* const [isOpen, setIsOpen] = useState(false);
|
|
82
|
+
* <BottomSheet
|
|
83
|
+
* isOpen={isOpen}
|
|
84
|
+
* onOpenChange={setIsOpen}
|
|
85
|
+
* label="Filters">
|
|
86
|
+
* <FilterControls />
|
|
87
|
+
* </BottomSheet>
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function BottomSheet({ isOpen, onOpenChange, label, children, height, xstyle, ...props }: BottomSheetProps): import("react").JSX.Element;
|
|
91
|
+
export declare namespace BottomSheet {
|
|
92
|
+
var displayName: string;
|
|
93
|
+
}
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=BottomSheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAUlD;;;;GAIG;AACH,QAAA,MAAM,cAAc;;;;;CAKV,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,cAAc,CAAC;AAoE5D,MAAM,WAAW,gBAAiB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACpE,wDAAwD;IACxD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;OAIG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAExC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,MAAiB,EACjB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,gBAAgB,+BAoClB;yBA5Ce,WAAW"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file BottomSheet.tsx
|
|
7
|
+
* @input Uses React, StyleX, theme tokens, Drawer, useSheetGestures, themeProps
|
|
8
|
+
* @output Exports BottomSheet component and BottomSheetProps
|
|
9
|
+
* @position Lab implementation; consumed by index.ts, tested by BottomSheet.test.tsx, demonstrated in Storybook
|
|
10
|
+
*
|
|
11
|
+
* A mobile touch surface that rises from the bottom edge with a grab handle
|
|
12
|
+
* and swipe-to-dismiss. Built ON TOP OF the lab Drawer's native `<dialog>`
|
|
13
|
+
* engine (`side="bottom"`) rather than forking it — Drawer owns
|
|
14
|
+
* showModal/show, the open/close slide animation, focus trap + restore,
|
|
15
|
+
* scroll lock, the Escape/scrim contract, and the LIFO overlay registry.
|
|
16
|
+
* BottomSheet layers the grab handle and the drag-to-dismiss gesture on top,
|
|
17
|
+
* inside the dialog.
|
|
18
|
+
*
|
|
19
|
+
* The gesture translate is applied to an inner sheet wrapper, not the
|
|
20
|
+
* `<dialog>` itself, so Drawer owns the open/close slide and the drag
|
|
21
|
+
* translates within it without the two transforms fighting.
|
|
22
|
+
*
|
|
23
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
24
|
+
* - /packages/lab/src/BottomSheet/BottomSheet.doc.mjs (props table, features, usage)
|
|
25
|
+
* - /packages/lab/src/BottomSheet/BottomSheet.test.tsx (tests for new/changed behavior)
|
|
26
|
+
* - /packages/lab/src/BottomSheet/index.ts (exports if types change)
|
|
27
|
+
* - /apps/storybook/stories/BottomSheet.stories.tsx (examples and visual coverage)
|
|
28
|
+
*/
|
|
29
|
+
import * as stylex from '@stylexjs/stylex';
|
|
30
|
+
import '@astryxdesign/core/theme/tokens.stylex';
|
|
31
|
+
import { colorVars, radiusVars, spacingVars } from '@astryxdesign/core/theme/tokens.stylex';
|
|
32
|
+
import { mergeProps, themeProps } from '@astryxdesign/core/utils';
|
|
33
|
+
import { Drawer } from "../Drawer/index.js";
|
|
34
|
+
import { useSheetGestures } from "./useSheetGestures.js";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Height budget for each named size. `medium`/`tall` track the viewport so
|
|
38
|
+
* the sheet scales with the device; `short` is a fixed peek height. `auto`
|
|
39
|
+
* is handled separately (fits content, capped at the `tall` budget).
|
|
40
|
+
*/
|
|
41
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
42
|
+
const HEIGHT_BUDGETS = {
|
|
43
|
+
short: '240px',
|
|
44
|
+
medium: '50dvh',
|
|
45
|
+
tall: '90dvh',
|
|
46
|
+
auto: '90dvh'
|
|
47
|
+
};
|
|
48
|
+
// Sheets on wide touch devices (tablets) shouldn't stretch edge to edge;
|
|
49
|
+
// cap and center them. Matches the `sm` layout breakpoint. On phones the
|
|
50
|
+
// viewport is narrower than this, so the sheet stays full-width.
|
|
51
|
+
const MAX_SHEET_WIDTH = 640;
|
|
52
|
+
const styles = {
|
|
53
|
+
sheet: {
|
|
54
|
+
k1xSpc: "x78zum5",
|
|
55
|
+
kXwgrk: "xdt5ytf",
|
|
56
|
+
kAzted: "x2lwn1j",
|
|
57
|
+
kZKoxP: "x5yr21d",
|
|
58
|
+
kzqmXN: "xh8yej3",
|
|
59
|
+
ks0D6T: "x11gisft",
|
|
60
|
+
kUOVxO: "xvueqy4",
|
|
61
|
+
kWkggS: "x10xzikg",
|
|
62
|
+
krdFHd: "x183tx6i",
|
|
63
|
+
kfmiAY: "x663v1",
|
|
64
|
+
kVQacm: "xb3r6kr",
|
|
65
|
+
kGO01o: "x1a148e8",
|
|
66
|
+
k6sLGO: "x1so62im",
|
|
67
|
+
$$css: true
|
|
68
|
+
},
|
|
69
|
+
dialogSurface: {
|
|
70
|
+
kWkggS: "xjbqb8w",
|
|
71
|
+
kGVxlE: "x1gnnqk1",
|
|
72
|
+
kEafiO: "x972fbf",
|
|
73
|
+
$$css: true
|
|
74
|
+
},
|
|
75
|
+
autoHeight: {
|
|
76
|
+
kZKoxP: "xg7h5cd",
|
|
77
|
+
kskxy: "x1ismmbu",
|
|
78
|
+
$$css: true
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* A mobile touch sheet that rises from the bottom edge, with a grab handle
|
|
83
|
+
* and swipe-to-dismiss. Built on the lab Drawer's `<dialog>` engine
|
|
84
|
+
* (`side="bottom"`): Drawer owns the open/close slide, focus trap + restore,
|
|
85
|
+
* scroll lock, and the Escape/scrim contract, while BottomSheet layers the
|
|
86
|
+
* grab handle and drag-to-dismiss on top.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```
|
|
90
|
+
* const [isOpen, setIsOpen] = useState(false);
|
|
91
|
+
* <BottomSheet
|
|
92
|
+
* isOpen={isOpen}
|
|
93
|
+
* onOpenChange={setIsOpen}
|
|
94
|
+
* label="Filters">
|
|
95
|
+
* <FilterControls />
|
|
96
|
+
* </BottomSheet>
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function BottomSheet({
|
|
100
|
+
isOpen,
|
|
101
|
+
onOpenChange,
|
|
102
|
+
label,
|
|
103
|
+
children,
|
|
104
|
+
height = 'medium',
|
|
105
|
+
xstyle,
|
|
106
|
+
...props
|
|
107
|
+
}) {
|
|
108
|
+
const close = () => onOpenChange(false);
|
|
109
|
+
const {
|
|
110
|
+
contentProps,
|
|
111
|
+
handleProps
|
|
112
|
+
} = useSheetGestures({
|
|
113
|
+
isOpen,
|
|
114
|
+
onDismiss: close
|
|
115
|
+
});
|
|
116
|
+
return /*#__PURE__*/_jsx(Drawer, {
|
|
117
|
+
isOpen: isOpen,
|
|
118
|
+
onClose: close,
|
|
119
|
+
side: "bottom",
|
|
120
|
+
size: HEIGHT_BUDGETS[height],
|
|
121
|
+
label: label,
|
|
122
|
+
hasScrim: true,
|
|
123
|
+
hasCloseButton: false,
|
|
124
|
+
xstyle: [styles.dialogSurface, height === 'auto' && styles.autoHeight],
|
|
125
|
+
...props,
|
|
126
|
+
children: /*#__PURE__*/_jsxs("div", {
|
|
127
|
+
"data-astryx-sheet": "",
|
|
128
|
+
...mergeProps(themeProps('bottom-sheet'), stylex.props(styles.sheet, xstyle), contentProps.style),
|
|
129
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
130
|
+
"data-astryx-sheet-handle": "",
|
|
131
|
+
...{
|
|
132
|
+
className: "x2lah0s x78zum5 x6s0dn4 xl56j7k xce4md1 x5ve5x3 x1jm3nie"
|
|
133
|
+
},
|
|
134
|
+
...handleProps,
|
|
135
|
+
"aria-hidden": "true",
|
|
136
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
137
|
+
...{
|
|
138
|
+
className: "x14qfxbe xqu0tyb xjspbzw x1m4xfpy"
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
142
|
+
...{
|
|
143
|
+
className: "x1iyjqo2 x2lwn1j x1odjw0f xish69e"
|
|
144
|
+
},
|
|
145
|
+
children: children
|
|
146
|
+
})]
|
|
147
|
+
})
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
BottomSheet.displayName = 'BottomSheet';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @input BottomSheet.tsx
|
|
4
|
+
* @output Re-exports BottomSheet component and BottomSheetProps type
|
|
5
|
+
* @position Lab entry point for the BottomSheet directory
|
|
6
|
+
*/
|
|
7
|
+
export { BottomSheet } from './BottomSheet';
|
|
8
|
+
export type { BottomSheetProps } from './BottomSheet';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file index.ts
|
|
5
|
+
* @input BottomSheet.tsx
|
|
6
|
+
* @output Re-exports BottomSheet component and BottomSheetProps type
|
|
7
|
+
* @position Lab entry point for the BottomSheet directory
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export { BottomSheet } from "./BottomSheet.js";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file useSheetGestures.ts
|
|
3
|
+
* @input Uses React (useCallback, useEffect, useMemo, useRef, useState)
|
|
4
|
+
* @output Exports useSheetGestures hook and its option/result types
|
|
5
|
+
* @position Internal to BottomSheet; not exported from the lab entry point
|
|
6
|
+
*
|
|
7
|
+
* Drag-to-dismiss machinery for the bottom sheet. Tracks a pointer drag
|
|
8
|
+
* down the block axis, translates the sliding surface live, and on release
|
|
9
|
+
* either dismisses (past a distance or velocity threshold) or springs back
|
|
10
|
+
* to fully open. Pointer-events based so one code path covers mouse + touch.
|
|
11
|
+
*
|
|
12
|
+
* Kept private to BottomSheet: the behavior is sheet-specific (a dismiss
|
|
13
|
+
* edge on a bottom-anchored surface). It is not a general primitive and is
|
|
14
|
+
* intentionally not exported.
|
|
15
|
+
*
|
|
16
|
+
* SSR-safe: no window/document access at module scope; all measurement
|
|
17
|
+
* happens inside handlers. Respects prefers-reduced-motion by skipping the
|
|
18
|
+
* settle transition.
|
|
19
|
+
*
|
|
20
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
21
|
+
* - /packages/lab/src/BottomSheet/useSheetGestures.doc.mjs
|
|
22
|
+
* - /packages/lab/src/BottomSheet/useSheetGestures.test.ts
|
|
23
|
+
*/
|
|
24
|
+
import { type CSSProperties, type PointerEvent as ReactPointerEvent } from 'react';
|
|
25
|
+
export interface UseSheetGesturesOptions {
|
|
26
|
+
/** Whether the owning sheet is open. Drag state resets when it closes. */
|
|
27
|
+
isOpen: boolean;
|
|
28
|
+
/** Called when a drag crosses the dismiss threshold (distance or flick). */
|
|
29
|
+
onDismiss: () => void;
|
|
30
|
+
}
|
|
31
|
+
export interface SheetContentProps {
|
|
32
|
+
style: CSSProperties;
|
|
33
|
+
}
|
|
34
|
+
export interface SheetHandleProps {
|
|
35
|
+
style: CSSProperties;
|
|
36
|
+
onPointerDown: (event: ReactPointerEvent) => void;
|
|
37
|
+
onPointerMove: (event: ReactPointerEvent) => void;
|
|
38
|
+
onPointerUp: (event: ReactPointerEvent) => void;
|
|
39
|
+
onPointerCancel: (event: ReactPointerEvent) => void;
|
|
40
|
+
}
|
|
41
|
+
export interface UseSheetGesturesResult {
|
|
42
|
+
/** Spread on the sliding surface: live translate + touch-action guard. */
|
|
43
|
+
contentProps: SheetContentProps;
|
|
44
|
+
/** Spread on the grab-handle element: pointer drag handlers. */
|
|
45
|
+
handleProps: SheetHandleProps;
|
|
46
|
+
/** Current live drag offset in px (positive = dragged toward the edge). */
|
|
47
|
+
dragOffset: number;
|
|
48
|
+
/** Whether a drag is currently in progress. */
|
|
49
|
+
isDragging: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Drag-to-dismiss machinery for the bottom sheet. Returns props to spread on
|
|
53
|
+
* the grab handle and the sliding surface, plus live drag state for callers
|
|
54
|
+
* that want to drive their own animation.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```
|
|
58
|
+
* const {contentProps, handleProps} = useSheetGestures({
|
|
59
|
+
* isOpen,
|
|
60
|
+
* onDismiss: () => onOpenChange(false),
|
|
61
|
+
* });
|
|
62
|
+
* <div {...contentProps}>
|
|
63
|
+
* <div {...handleProps} />
|
|
64
|
+
* {children}
|
|
65
|
+
* </div>
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function useSheetGestures({ isOpen, onDismiss, }: UseSheetGesturesOptions): UseSheetGesturesResult;
|
|
69
|
+
//# sourceMappingURL=useSheetGestures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSheetGestures.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/useSheetGestures.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,YAAY,IAAI,iBAAiB,EACvC,MAAM,OAAO,CAAC;AAQf,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClD,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD,eAAe,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,YAAY,EAAE,iBAAiB,CAAC;IAChC,gEAAgE;IAChE,WAAW,EAAE,gBAAgB,CAAC;IAC9B,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;CACrB;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,SAAS,GACV,EAAE,uBAAuB,GAAG,sBAAsB,CA4HlD"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useSheetGestures.ts
|
|
7
|
+
* @input Uses React (useCallback, useEffect, useMemo, useRef, useState)
|
|
8
|
+
* @output Exports useSheetGestures hook and its option/result types
|
|
9
|
+
* @position Internal to BottomSheet; not exported from the lab entry point
|
|
10
|
+
*
|
|
11
|
+
* Drag-to-dismiss machinery for the bottom sheet. Tracks a pointer drag
|
|
12
|
+
* down the block axis, translates the sliding surface live, and on release
|
|
13
|
+
* either dismisses (past a distance or velocity threshold) or springs back
|
|
14
|
+
* to fully open. Pointer-events based so one code path covers mouse + touch.
|
|
15
|
+
*
|
|
16
|
+
* Kept private to BottomSheet: the behavior is sheet-specific (a dismiss
|
|
17
|
+
* edge on a bottom-anchored surface). It is not a general primitive and is
|
|
18
|
+
* intentionally not exported.
|
|
19
|
+
*
|
|
20
|
+
* SSR-safe: no window/document access at module scope; all measurement
|
|
21
|
+
* happens inside handlers. Respects prefers-reduced-motion by skipping the
|
|
22
|
+
* settle transition.
|
|
23
|
+
*
|
|
24
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
25
|
+
* - /packages/lab/src/BottomSheet/useSheetGestures.doc.mjs
|
|
26
|
+
* - /packages/lab/src/BottomSheet/useSheetGestures.test.ts
|
|
27
|
+
*/
|
|
28
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
29
|
+
|
|
30
|
+
// Fraction of the measured sheet height a drag must cross (with low
|
|
31
|
+
// velocity) before release dismisses instead of springing back.
|
|
32
|
+
const DISMISS_DISTANCE_RATIO = 0.25;
|
|
33
|
+
// A quick flick past this speed (px/ms) dismisses regardless of distance.
|
|
34
|
+
const DISMISS_VELOCITY = 0.5;
|
|
35
|
+
function prefersReducedMotion() {
|
|
36
|
+
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Drag-to-dismiss machinery for the bottom sheet. Returns props to spread on
|
|
44
|
+
* the grab handle and the sliding surface, plus live drag state for callers
|
|
45
|
+
* that want to drive their own animation.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```
|
|
49
|
+
* const {contentProps, handleProps} = useSheetGestures({
|
|
50
|
+
* isOpen,
|
|
51
|
+
* onDismiss: () => onOpenChange(false),
|
|
52
|
+
* });
|
|
53
|
+
* <div {...contentProps}>
|
|
54
|
+
* <div {...handleProps} />
|
|
55
|
+
* {children}
|
|
56
|
+
* </div>
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function useSheetGestures({
|
|
60
|
+
isOpen,
|
|
61
|
+
onDismiss
|
|
62
|
+
}) {
|
|
63
|
+
const [dragOffset, setDragOffset] = useState(0);
|
|
64
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
65
|
+
|
|
66
|
+
// Latest callback ref so pointer handlers stay stable across renders.
|
|
67
|
+
const onDismissRef = useRef(onDismiss);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
onDismissRef.current = onDismiss;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Live drag bookkeeping (refs so pointermove doesn't churn renders).
|
|
73
|
+
const dragStateRef = useRef(null);
|
|
74
|
+
|
|
75
|
+
// Reset drag state each time the sheet re-opens.
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (isOpen) {
|
|
78
|
+
setDragOffset(0);
|
|
79
|
+
setIsDragging(false);
|
|
80
|
+
}
|
|
81
|
+
}, [isOpen]);
|
|
82
|
+
const measureHeight = useCallback(el => {
|
|
83
|
+
const sheet = el?.closest('[data-astryx-sheet]') ?? el;
|
|
84
|
+
return sheet?.getBoundingClientRect().height ?? 0;
|
|
85
|
+
}, []);
|
|
86
|
+
const settleFromDrag = useCallback((offset, velocity, height) => {
|
|
87
|
+
const dismiss = offset > height * DISMISS_DISTANCE_RATIO || velocity > DISMISS_VELOCITY;
|
|
88
|
+
if (dismiss) {
|
|
89
|
+
onDismissRef.current();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Below threshold: spring back to fully open.
|
|
93
|
+
setDragOffset(0);
|
|
94
|
+
}, []);
|
|
95
|
+
const handlePointerDown = useCallback(event => {
|
|
96
|
+
const target = event.currentTarget;
|
|
97
|
+
target.setPointerCapture?.(event.pointerId);
|
|
98
|
+
dragStateRef.current = {
|
|
99
|
+
pointerId: event.pointerId,
|
|
100
|
+
startCoord: event.clientY,
|
|
101
|
+
lastCoord: event.clientY,
|
|
102
|
+
lastTime: event.timeStamp,
|
|
103
|
+
velocity: 0,
|
|
104
|
+
height: measureHeight(target)
|
|
105
|
+
};
|
|
106
|
+
setIsDragging(true);
|
|
107
|
+
}, [measureHeight]);
|
|
108
|
+
const handlePointerMove = useCallback(event => {
|
|
109
|
+
const state = dragStateRef.current;
|
|
110
|
+
if (!state || state.pointerId !== event.pointerId) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Dragging DOWN (increasing Y) collapses/dismisses. Only allow drag in
|
|
114
|
+
// the closing direction past the fully-open position (no overscroll).
|
|
115
|
+
const delta = event.clientY - state.startCoord;
|
|
116
|
+
const dt = event.timeStamp - state.lastTime;
|
|
117
|
+
if (dt > 0) {
|
|
118
|
+
state.velocity = (event.clientY - state.lastCoord) / dt;
|
|
119
|
+
state.lastCoord = event.clientY;
|
|
120
|
+
state.lastTime = event.timeStamp;
|
|
121
|
+
}
|
|
122
|
+
setDragOffset(Math.max(0, delta));
|
|
123
|
+
}, []);
|
|
124
|
+
const endDrag = useCallback(event => {
|
|
125
|
+
const state = dragStateRef.current;
|
|
126
|
+
if (!state || state.pointerId !== event.pointerId) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const target = event.currentTarget;
|
|
130
|
+
target.releasePointerCapture?.(event.pointerId);
|
|
131
|
+
const offset = Math.max(0, event.clientY - state.startCoord);
|
|
132
|
+
dragStateRef.current = null;
|
|
133
|
+
setIsDragging(false);
|
|
134
|
+
settleFromDrag(offset, state.velocity, state.height || 1);
|
|
135
|
+
}, [settleFromDrag]);
|
|
136
|
+
|
|
137
|
+
// Reduced motion skips the settle transition (snaps instantly).
|
|
138
|
+
const reducedMotion = useMemo(prefersReducedMotion, [isOpen]);
|
|
139
|
+
const contentProps = useMemo(() => ({
|
|
140
|
+
style: {
|
|
141
|
+
transform: dragOffset !== 0 ? `translateY(${dragOffset}px)` : undefined,
|
|
142
|
+
transition: isDragging || reducedMotion ? 'none' : undefined,
|
|
143
|
+
touchAction: 'none',
|
|
144
|
+
overscrollBehavior: 'contain'
|
|
145
|
+
}
|
|
146
|
+
}), [dragOffset, isDragging, reducedMotion]);
|
|
147
|
+
const handleProps = useMemo(() => ({
|
|
148
|
+
style: {
|
|
149
|
+
touchAction: 'none',
|
|
150
|
+
cursor: 'grab'
|
|
151
|
+
},
|
|
152
|
+
onPointerDown: handlePointerDown,
|
|
153
|
+
onPointerMove: handlePointerMove,
|
|
154
|
+
onPointerUp: endDrag,
|
|
155
|
+
onPointerCancel: endDrag
|
|
156
|
+
}), [handlePointerDown, handlePointerMove, endDrag]);
|
|
157
|
+
return {
|
|
158
|
+
contentProps,
|
|
159
|
+
handleProps,
|
|
160
|
+
dragOffset,
|
|
161
|
+
isDragging
|
|
162
|
+
};
|
|
163
|
+
}
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
import { type ReactNode } from 'react';
|
|
23
23
|
import type { BaseProps } from '@astryxdesign/core';
|
|
24
24
|
import type { SizeValue } from '@astryxdesign/core/utils';
|
|
25
|
+
import { type Transformer } from '@lexical/markdown';
|
|
26
|
+
export type { Transformer } from '@lexical/markdown';
|
|
25
27
|
import type { EditorState, Klass, LexicalEditor, LexicalNode } from 'lexical';
|
|
26
28
|
export type RichTextEditorStatusType = 'warning' | 'error' | 'success';
|
|
27
29
|
export type RichTextEditorSize = 'sm' | 'md' | 'lg';
|
|
@@ -31,6 +33,36 @@ export interface RichTextEditorStatus {
|
|
|
31
33
|
/** Optional message to display below the editor. */
|
|
32
34
|
message?: string;
|
|
33
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Imperative handle exposed via `ref`. Lets callers focus, clear, and read the
|
|
38
|
+
* editor without wiring a custom plugin. Available after mount.
|
|
39
|
+
*/
|
|
40
|
+
export interface RichTextEditorRef {
|
|
41
|
+
/**
|
|
42
|
+
* Move focus into the editor's editable surface. No-op when the editor is
|
|
43
|
+
* read-only or disabled.
|
|
44
|
+
*/
|
|
45
|
+
focus: () => void;
|
|
46
|
+
/**
|
|
47
|
+
* Remove all content, resetting the editor to a single empty paragraph.
|
|
48
|
+
* No-op when the editor is read-only or disabled.
|
|
49
|
+
*/
|
|
50
|
+
clear: () => void;
|
|
51
|
+
/** Read the current `EditorState`. Serialize with `.toJSON()` to persist. */
|
|
52
|
+
getEditorState: () => EditorState;
|
|
53
|
+
/**
|
|
54
|
+
* Serialize the current content to a Markdown string, using the same
|
|
55
|
+
* `transformers` the editor is configured with (so custom transformers
|
|
56
|
+
* layered in via the `transformers` prop are honored). Equivalent to
|
|
57
|
+
* `$convertToMarkdownString` run in a read context.
|
|
58
|
+
*/
|
|
59
|
+
getMarkdown: () => string;
|
|
60
|
+
/**
|
|
61
|
+
* Access the underlying `LexicalEditor` instance for advanced use cases
|
|
62
|
+
* (custom commands, listeners, node transforms).
|
|
63
|
+
*/
|
|
64
|
+
getEditor: () => LexicalEditor;
|
|
65
|
+
}
|
|
34
66
|
export interface RichTextEditorProps extends Omit<BaseProps, 'onChange' | 'defaultValue'> {
|
|
35
67
|
/** Label text for the editor (always rendered for accessibility). */
|
|
36
68
|
label: string;
|
|
@@ -106,12 +138,39 @@ export interface RichTextEditorProps extends Omit<BaseProps, 'onChange' | 'defau
|
|
|
106
138
|
plugins?: ReactNode;
|
|
107
139
|
/**
|
|
108
140
|
* Whether to enable Markdown shortcut typing (e.g. `# ` for a heading,
|
|
109
|
-
* `- ` for a list). Uses the
|
|
141
|
+
* `- ` for a list). Uses the `transformers` prop (defaults to the standard
|
|
142
|
+
* `@lexical/markdown` transformers).
|
|
110
143
|
* @default true
|
|
111
144
|
*/
|
|
112
145
|
hasMarkdownShortcuts?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Markdown transformers — the single source of truth for markdown behaviour.
|
|
148
|
+
* Defaults to the standard `@lexical/markdown` `TRANSFORMERS`.
|
|
149
|
+
*
|
|
150
|
+
* The same array drives all three markdown operations in Lexical (see the
|
|
151
|
+
* lexical-playground reference, where one `PLAYGROUND_TRANSFORMERS` array
|
|
152
|
+
* feeds each):
|
|
153
|
+
* - shortcut typing — `registerMarkdownShortcuts` (wired here today)
|
|
154
|
+
* - markdown -> state — `$convertFromMarkdownString` (future import API)
|
|
155
|
+
* - state -> markdown — `$convertToMarkdownString` (future `getMarkdown`)
|
|
156
|
+
*
|
|
157
|
+
* Pass a custom array to support additional node types (e.g. custom
|
|
158
|
+
* transformers layered in via the `nodes` extension point) consistently
|
|
159
|
+
* across all three. Shortcut typing is only applied when
|
|
160
|
+
* `hasMarkdownShortcuts` is true; the array is still the intended input for
|
|
161
|
+
* the serialization APIs added in later phases.
|
|
162
|
+
*/
|
|
163
|
+
transformers?: ReadonlyArray<Transformer>;
|
|
113
164
|
/** Whether to automatically focus the editor on mount. @default false */
|
|
114
165
|
hasAutoFocus?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Maximum number of characters. When set, a character counter
|
|
168
|
+
* (current/max) is displayed below the editor. Like TextArea, this does
|
|
169
|
+
* NOT enforce the limit natively — the counter shows error styling when the
|
|
170
|
+
* plain-text length exceeds the limit. Count is the editor's plain-text
|
|
171
|
+
* content length.
|
|
172
|
+
*/
|
|
173
|
+
maxLength?: number;
|
|
115
174
|
/**
|
|
116
175
|
* The Lexical composer namespace, used for editor identity.
|
|
117
176
|
* @default 'astryx-editor'
|
|
@@ -128,18 +187,20 @@ export interface RichTextEditorProps extends Omit<BaseProps, 'onChange' | 'defau
|
|
|
128
187
|
* `plugins` to layer richer behaviour (toolbars, mentions, hover cards) on top
|
|
129
188
|
* without forking.
|
|
130
189
|
*
|
|
190
|
+
* The forwarded `RichTextEditorRef` exposes imperative `focus()` and `clear()`
|
|
191
|
+
* methods for callers that manage the editor from outside.
|
|
192
|
+
*
|
|
131
193
|
* @example
|
|
132
194
|
* ```
|
|
133
|
-
* import {RichTextEditor} from '@astryxdesign/lab';
|
|
195
|
+
* import {RichTextEditor, type RichTextEditorRef} from '@astryxdesign/lab';
|
|
196
|
+
* const ref = useRef<RichTextEditorRef>(null);
|
|
134
197
|
* <RichTextEditor
|
|
198
|
+
* ref={ref}
|
|
135
199
|
* label="Notes"
|
|
136
200
|
* placeholder="Write something..."
|
|
137
201
|
* onChange={state => save(JSON.stringify(state.toJSON()))}
|
|
138
202
|
* />
|
|
139
203
|
* ```
|
|
140
204
|
*/
|
|
141
|
-
export declare
|
|
142
|
-
export declare namespace RichTextEditor {
|
|
143
|
-
var displayName: string;
|
|
144
|
-
}
|
|
205
|
+
export declare const RichTextEditor: import("react").ForwardRefExoticComponent<RichTextEditorProps & import("react").RefAttributes<RichTextEditorRef>>;
|
|
145
206
|
//# sourceMappingURL=RichTextEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditor.d.ts","sourceRoot":"","sources":["../../src/RichTextEditor/RichTextEditor.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"RichTextEditor.d.ts","sourceRoot":"","sources":["../../src/RichTextEditor/RichTextEditor.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAQL,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAgBf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAkBxD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAKnD,OAAO,KAAK,EACV,WAAW,EACX,KAAK,EACL,aAAa,EACb,WAAW,EAEZ,MAAM,SAAS,CAAC;AAoHjB,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvE,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;OAGG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,WAAW,CAAC;IAClC;;;;;OAKG;IACH,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,EAAE,MAAM,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,SAAS,EACT,UAAU,GAAG,cAAc,CAC5B;IACC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACrE,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC1C;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,cAAc,mHAuLzB,CAAC"}
|