@ciridae/ui 1.0.4 → 1.0.9
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 +3 -2
- package/dist/chat/conversation-source.d.ts +1 -3
- package/dist/chat/message-text.js +6 -6
- package/dist/chat/use-chat-conversation.d.ts +7 -2
- package/dist/chat/use-chat-conversation.js +2 -1
- package/dist/components/activity-feed.d.ts +0 -1
- package/dist/components/activity-feed.js +6 -7
- package/dist/components/agent-work.d.ts +5 -1
- package/dist/components/agent-work.js +27 -13
- package/dist/components/app-frame.d.ts +3 -17
- package/dist/components/app-frame.js +11 -30
- package/dist/components/app-navigation.d.ts +5 -6
- package/dist/components/app-navigation.js +70 -40
- package/dist/components/badge.d.ts +0 -4
- package/dist/components/badge.js +17 -27
- package/dist/components/bulk-action-bar.js +2 -2
- package/dist/components/button.js +41 -50
- package/dist/components/calendar.js +5 -8
- package/dist/components/centered-page.js +4 -4
- package/dist/components/chart.js +3 -4
- package/dist/components/chat-client-source.js +55 -34
- package/dist/components/chat-page.js +1 -1
- package/dist/components/chat-sheet.d.ts +30 -20
- package/dist/components/chat-sheet.js +112 -54
- package/dist/components/chat.d.ts +27 -56
- package/dist/components/chat.js +153 -132
- package/dist/components/checkbox-item.js +4 -4
- package/dist/components/checkbox-list.js +6 -6
- package/dist/components/chip.js +2 -2
- package/dist/components/collapsible.js +3 -3
- package/dist/components/color-theme.d.ts +3 -6
- package/dist/components/color-theme.js +10 -11
- package/dist/components/column-settings.js +3 -3
- package/dist/components/command-menu.d.ts +1 -2
- package/dist/components/command-menu.js +56 -77
- package/dist/components/command-palette.js +5 -2
- package/dist/components/copyable-id.js +5 -5
- package/dist/components/data-display.d.ts +1 -7
- package/dist/components/data-display.js +32 -55
- package/dist/components/data-grid.d.ts +4 -7
- package/dist/components/data-grid.js +106 -90
- package/dist/components/date-range-picker.js +4 -5
- package/dist/components/document-viewer.js +23 -23
- package/dist/components/drawer.d.ts +2 -1
- package/dist/components/drawer.js +45 -20
- package/dist/components/dropzone.js +13 -13
- package/dist/components/editable-field.d.ts +2 -7
- package/dist/components/editable-field.js +14 -27
- package/dist/components/email-input.js +2 -3
- package/dist/components/environment-frame.js +7 -7
- package/dist/components/expandable-text.js +2 -2
- package/dist/components/feedback-screenshot.js +7 -7
- package/dist/components/feedback-sheet.js +8 -8
- package/dist/components/filter-bar.js +41 -27
- package/dist/components/form-controls.d.ts +3 -6
- package/dist/components/form-controls.js +15 -22
- package/dist/components/form-layout.d.ts +6 -6
- package/dist/components/form-layout.js +10 -16
- package/dist/components/glass-menu.d.ts +2 -0
- package/dist/components/glass-menu.js +14 -18
- package/dist/components/gradient-edge.d.ts +0 -1
- package/dist/components/gradient-edge.js +8 -9
- package/dist/components/icon.js +1 -1
- package/dist/components/input.js +18 -17
- package/dist/components/keycap.d.ts +2 -6
- package/dist/components/keycap.js +4 -12
- package/dist/components/layout.js +11 -10
- package/dist/components/lightbox.js +8 -8
- package/dist/components/link.js +1 -1
- package/dist/components/locale.d.ts +23 -7
- package/dist/components/locale.js +19 -7
- package/dist/components/log-entry.d.ts +2 -14
- package/dist/components/log-entry.js +11 -22
- package/dist/components/log-list.js +1 -1
- package/dist/components/mention-input.js +13 -14
- package/dist/components/menu.d.ts +7 -4
- package/dist/components/menu.js +23 -10
- package/dist/components/meter.d.ts +2 -3
- package/dist/components/meter.js +12 -16
- package/dist/components/navigation.d.ts +0 -7
- package/dist/components/navigation.js +3 -12
- package/dist/components/notification-tray.js +7 -7
- package/dist/components/overlays.d.ts +5 -2
- package/dist/components/overlays.js +24 -24
- package/dist/components/panel.js +3 -3
- package/dist/components/progress.js +2 -2
- package/dist/components/radio-card.d.ts +1 -1
- package/dist/components/radio-card.js +9 -9
- package/dist/components/record.d.ts +2 -4
- package/dist/components/record.js +19 -32
- package/dist/components/scroll-area.js +10 -10
- package/dist/components/segmented-bar.js +9 -9
- package/dist/components/select.d.ts +3 -5
- package/dist/components/select.js +26 -44
- package/dist/components/settings.js +1 -1
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +1 -1
- package/dist/components/shell.js +69 -24
- package/dist/components/side-panel.js +3 -3
- package/dist/components/sidebar.d.ts +0 -5
- package/dist/components/sidebar.js +25 -33
- package/dist/components/single-line-text.js +3 -4
- package/dist/components/site-banner.js +4 -4
- package/dist/components/skeleton.js +19 -22
- package/dist/components/skeletons.d.ts +0 -3
- package/dist/components/skeletons.js +5 -10
- package/dist/components/stages.d.ts +6 -3
- package/dist/components/stages.js +77 -105
- package/dist/components/stat-card.d.ts +2 -5
- package/dist/components/stat-card.js +23 -31
- package/dist/components/status-banner.js +6 -6
- package/dist/components/status.js +3 -3
- package/dist/components/steps.js +2 -2
- package/dist/components/switch.js +1 -1
- package/dist/components/tabs.js +15 -18
- package/dist/components/theme-customizer.d.ts +5 -8
- package/dist/components/theme-customizer.js +9 -41
- package/dist/components/theme-toggle.d.ts +0 -1
- package/dist/components/theme-toggle.js +6 -11
- package/dist/components/toast.d.ts +1 -7
- package/dist/components/toast.js +19 -22
- package/dist/components/user-chip.js +8 -8
- package/dist/components/wizard.js +6 -4
- package/dist/preset.d.ts +1 -2
- package/dist/preset.js +41 -89
- package/dist/styled-system/css/conditions.mjs +1 -1
- package/dist/styled-system/css/css.mjs +1 -1
- package/dist/styled-system/styles.css +820 -1297
- package/dist/styled-system/tokens/index.mjs +78 -1926
- package/dist/styled-system/tokens/tokens.d.ts +18 -33
- package/dist/styled-system/types/conditions.d.ts +0 -74
- package/dist/styled-system/types/prop-type.d.ts +15 -40
- package/dist/styled-system/types/style-props.d.ts +705 -705
- package/dist/theme/color.d.ts +0 -1
- package/dist/theme/color.js +0 -16
- package/dist/theme/derive.d.ts +3 -3
- package/dist/theme/derive.js +9 -32
- package/dist/theme/index.d.ts +1 -2
- package/dist/theme/index.js +3 -5
- package/dist/theme/options.d.ts +2 -4
- package/dist/theme/options.js +0 -1
- package/dist/theme/{palettes.d.ts → palette.d.ts} +12 -23
- package/dist/theme/palette.js +127 -0
- package/dist/theme/tokens.d.ts +8 -13
- package/dist/theme/tokens.js +39 -92
- package/package.json +1 -1
- package/dist/theme/palettes.js +0 -254
|
@@ -82,7 +82,7 @@ const trigger = css({
|
|
|
82
82
|
paddingInline: "control.compactInline",
|
|
83
83
|
border: "1px solid transparent",
|
|
84
84
|
borderRadius: "action",
|
|
85
|
-
background: "token(gradients.selected)",
|
|
85
|
+
background: "[token(gradients.selected)]",
|
|
86
86
|
color: "fg.primary",
|
|
87
87
|
fontFamily: "sans",
|
|
88
88
|
fontSize: "body",
|
|
@@ -90,16 +90,15 @@ const trigger = css({
|
|
|
90
90
|
letterSpacing: "compact",
|
|
91
91
|
whiteSpace: "nowrap",
|
|
92
92
|
cursor: "pointer",
|
|
93
|
-
_hover: { background: "token(gradients.raisedHover)" },
|
|
93
|
+
_hover: { background: "[token(gradients.raisedHover)]" },
|
|
94
94
|
"&[data-popup-open]": { borderColor: "fg.primary" },
|
|
95
95
|
_focusVisible: { focusRing: "outer" },
|
|
96
96
|
});
|
|
97
|
-
const options = css({ display: "grid", width: "222px" });
|
|
98
|
-
// A menu row on the popover's glass sheet.
|
|
97
|
+
const options = css({ display: "grid", width: "[222px]" });
|
|
99
98
|
const option = css(glassMenuRow, {
|
|
100
99
|
border: "0",
|
|
101
100
|
background: "transparent",
|
|
102
|
-
fontFamily: "inherit",
|
|
101
|
+
fontFamily: "[inherit]",
|
|
103
102
|
textAlign: "start",
|
|
104
103
|
});
|
|
105
104
|
const optionsDivider = css(glassMenuDivider);
|
|
@@ -38,8 +38,8 @@ const viewer = css(cardSurface, {
|
|
|
38
38
|
gridTemplateRows: "auto minmax(0, 1fr)",
|
|
39
39
|
minWidth: "0",
|
|
40
40
|
overflow: "hidden",
|
|
41
|
-
outline: "
|
|
42
|
-
"&:fullscreen": { borderRadius: "
|
|
41
|
+
outline: "0",
|
|
42
|
+
"&:fullscreen": { borderRadius: "none", height: "[100dvh]" },
|
|
43
43
|
});
|
|
44
44
|
const toolbar = css({
|
|
45
45
|
display: "flex",
|
|
@@ -77,10 +77,10 @@ const zoomPill = css({
|
|
|
77
77
|
cursor: "pointer",
|
|
78
78
|
_hover: { background: "bg.hover" },
|
|
79
79
|
_focusVisible: { focusRing: "outer" },
|
|
80
|
-
_disabled: { opacity: "0.5", cursor: "default" },
|
|
80
|
+
_disabled: { opacity: "[0.5]", cursor: "default" },
|
|
81
81
|
},
|
|
82
82
|
"& > output": {
|
|
83
|
-
minWidth: "52px",
|
|
83
|
+
minWidth: "[52px]",
|
|
84
84
|
textAlign: "center",
|
|
85
85
|
fontSize: "body",
|
|
86
86
|
fontWeight: "medium",
|
|
@@ -90,7 +90,7 @@ const zoomPill = css({
|
|
|
90
90
|
const body = css({
|
|
91
91
|
display: "grid",
|
|
92
92
|
gridTemplateColumns: "104px minmax(0, 1fr)",
|
|
93
|
-
height: "min(693px, 80dvh)",
|
|
93
|
+
height: "[min(693px, 80dvh)]",
|
|
94
94
|
minHeight: "0",
|
|
95
95
|
_phone: { gridTemplateColumns: "minmax(0, 1fr)" },
|
|
96
96
|
"[data-full-screen] > &": { height: "auto" },
|
|
@@ -118,11 +118,11 @@ const thumbnail = css({
|
|
|
118
118
|
fontWeight: "medium",
|
|
119
119
|
cursor: "pointer",
|
|
120
120
|
"&[aria-current=page]": { color: "fg.primary" },
|
|
121
|
-
_focusVisible: { outline: "
|
|
121
|
+
_focusVisible: { outline: "0", "& > span": { focusRing: "outer" } },
|
|
122
122
|
"& > span": {
|
|
123
123
|
position: "relative",
|
|
124
124
|
overflow: "hidden",
|
|
125
|
-
borderRadius: "2px",
|
|
125
|
+
borderRadius: "[2px]",
|
|
126
126
|
outline: "1px solid token(colors.border.control)",
|
|
127
127
|
pointerEvents: "none",
|
|
128
128
|
},
|
|
@@ -130,28 +130,28 @@ const thumbnail = css({
|
|
|
130
130
|
});
|
|
131
131
|
const well = css({
|
|
132
132
|
display: "flex",
|
|
133
|
-
justifyContent: "safe center",
|
|
134
|
-
alignItems: "safe center",
|
|
135
|
-
padding: "24px",
|
|
133
|
+
justifyContent: "[safe center]",
|
|
134
|
+
alignItems: "[safe center]",
|
|
135
|
+
padding: "[24px]",
|
|
136
136
|
background: "bg.canvas",
|
|
137
137
|
overflow: "auto",
|
|
138
|
-
outline: "
|
|
138
|
+
outline: "0",
|
|
139
139
|
_focusVisible: { focusRing: "inset" },
|
|
140
140
|
});
|
|
141
141
|
const pageBox = css({ position: "relative", flexShrink: "0", boxShadow: "card" });
|
|
142
|
-
const pageLayer = css({ position: "absolute", top: "
|
|
142
|
+
const pageLayer = css({ position: "absolute", top: "none", left: "none", transformOrigin: "0 0" });
|
|
143
143
|
const pageContent = css({
|
|
144
144
|
position: "absolute",
|
|
145
|
-
top: "
|
|
146
|
-
left: "
|
|
145
|
+
top: "none",
|
|
146
|
+
left: "none",
|
|
147
147
|
transformOrigin: "0 0",
|
|
148
|
-
"& > img": { display: "block", width: "
|
|
148
|
+
"& > img": { display: "block", width: "full", height: "full" },
|
|
149
149
|
});
|
|
150
150
|
const regionButton = css({
|
|
151
151
|
position: "absolute",
|
|
152
152
|
padding: "none",
|
|
153
153
|
border: "1.5px solid transparent",
|
|
154
|
-
borderRadius: "3px",
|
|
154
|
+
borderRadius: "[3px]",
|
|
155
155
|
background: "transparent",
|
|
156
156
|
cursor: "pointer",
|
|
157
157
|
"--region-ink": "token(colors.accent.blue)",
|
|
@@ -175,16 +175,16 @@ const regionButton = css({
|
|
|
175
175
|
"&[data-marked], &:focus-visible": {
|
|
176
176
|
borderColor: "var(--region-ink)",
|
|
177
177
|
background: "var(--region-wash)",
|
|
178
|
-
outline: "
|
|
178
|
+
outline: "0",
|
|
179
179
|
},
|
|
180
180
|
"& > span": {
|
|
181
181
|
position: "absolute",
|
|
182
|
-
insetInlineStart: "-1.5px",
|
|
183
|
-
bottom: "calc(100% + 4px)",
|
|
182
|
+
insetInlineStart: "[-1.5px]",
|
|
183
|
+
bottom: "[calc(100% + 4px)]",
|
|
184
184
|
display: "none",
|
|
185
185
|
alignItems: "center",
|
|
186
|
-
height: "22px",
|
|
187
|
-
paddingInline: "6px",
|
|
186
|
+
height: "[22px]",
|
|
187
|
+
paddingInline: "[6px]",
|
|
188
188
|
borderRadius: "control",
|
|
189
189
|
background: "var(--region-ink)",
|
|
190
190
|
color: "fg.onAccent",
|
|
@@ -194,11 +194,11 @@ const regionButton = css({
|
|
|
194
194
|
whiteSpace: "nowrap",
|
|
195
195
|
pointerEvents: "none",
|
|
196
196
|
},
|
|
197
|
-
"&[data-near-top] > span": { bottom: "auto", top: "calc(100% + 4px)" },
|
|
197
|
+
"&[data-near-top] > span": { bottom: "[auto]", top: "[calc(100% + 4px)]" },
|
|
198
198
|
"&[data-marked] > span, &:focus-visible > span": { display: "inline-flex" },
|
|
199
199
|
});
|
|
200
200
|
const field = css({
|
|
201
|
-
width: "
|
|
201
|
+
width: "full",
|
|
202
202
|
padding: "none",
|
|
203
203
|
border: "0",
|
|
204
204
|
borderRadius: "keycap",
|
|
@@ -17,7 +17,8 @@ export type DrawerProps = Omit<ComponentProps<typeof BaseDrawer.Root>, "children
|
|
|
17
17
|
/**
|
|
18
18
|
* A sheet docked at the window's right edge beside the page, which stays usable: it is not modal
|
|
19
19
|
* and a click outside leaves it open, so Escape or its close button closes it. Pass `modal` or
|
|
20
|
-
* `disablePointerDismissal` to change either.
|
|
20
|
+
* `disablePointerDismissal` to change either. Closing gives the focus back to what had it when
|
|
21
|
+
* `open` turned on, such as a button outside the drawer or the page link a hotkey opened it from.
|
|
21
22
|
*/
|
|
22
23
|
export declare function Drawer({ title, icon: titleIcon, eyebrow, subtitle, titleAccessory, actions, size, children, ...rootProps }: DrawerProps): import("react").JSX.Element;
|
|
23
24
|
export declare function DrawerBody({ flush, className, ...props }: ComponentProps<"div"> & {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Drawer as BaseDrawer } from "@base-ui/react/drawer";
|
|
3
3
|
import { XIcon } from "@phosphor-icons/react";
|
|
4
|
-
import { useId, useMemo } from "react";
|
|
4
|
+
import { useId, useLayoutEffect, useMemo, useRef } from "react";
|
|
5
5
|
import { css, cva, cx } from "#primitives/css";
|
|
6
6
|
import { IconButton } from "./button.js";
|
|
7
7
|
import { FieldControlContext } from "./field-context.js";
|
|
@@ -11,9 +11,9 @@ import { Eyebrow, heading } from "./layout.js";
|
|
|
11
11
|
import { useCiridaeLocale } from "./locale.js";
|
|
12
12
|
const viewport = css({ position: "fixed", inset: "none", zIndex: "drawer", pointerEvents: "none" });
|
|
13
13
|
/*
|
|
14
|
-
* A drawer sits beside the page, which stays usable: no scrim
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* A drawer sits beside the page, which stays usable: no scrim. The shell's padding is what keeps
|
|
15
|
+
* the sheet off the window's edges, level with the main panel; a phone takes the sheet to the
|
|
16
|
+
* edges.
|
|
17
17
|
*/
|
|
18
18
|
const popup = cva({
|
|
19
19
|
base: {
|
|
@@ -23,41 +23,48 @@ const popup = cva({
|
|
|
23
23
|
display: "flex",
|
|
24
24
|
padding: "panel.compact",
|
|
25
25
|
pointerEvents: "auto",
|
|
26
|
-
outline: "
|
|
26
|
+
outline: "0",
|
|
27
27
|
textStyle: "body",
|
|
28
28
|
border: "1px solid token(colors.border.divider)",
|
|
29
29
|
borderRadius: "shell",
|
|
30
30
|
background: "bg.drawerShell",
|
|
31
|
-
backdropFilter: "blur(token(blurs.drawerShell))",
|
|
31
|
+
backdropFilter: "[blur(token(blurs.drawerShell))]",
|
|
32
32
|
boxShadow: "drawerShell",
|
|
33
|
-
|
|
33
|
+
// A phone's drawer covers the page, so it is opaque there rather than glass the page shows through.
|
|
34
|
+
_phone: {
|
|
35
|
+
padding: "none",
|
|
36
|
+
border: "0",
|
|
37
|
+
borderRadius: "none",
|
|
38
|
+
background: "bg.canvas",
|
|
39
|
+
backdropFilter: "[none]",
|
|
40
|
+
},
|
|
34
41
|
// Base UI drives live swipe drag through this custom property; the resting
|
|
35
42
|
// transform must reference it or dragging won't visually track the pointer.
|
|
36
43
|
transform: "translateX(var(--drawer-swipe-movement-x, 0px))",
|
|
37
|
-
transitionProperty: "transform",
|
|
44
|
+
transitionProperty: "[transform]",
|
|
38
45
|
transitionDuration: "default",
|
|
39
46
|
"&[data-starting-style], &[data-ending-style]": {
|
|
40
47
|
transform: "translateX(100%)",
|
|
41
48
|
_rtl: { transform: "translateX(-100%)" },
|
|
42
49
|
},
|
|
43
|
-
"&[data-swiping]": { transitionDuration: "0ms" },
|
|
44
|
-
_motionReduce: { transitionDuration: "0ms" },
|
|
50
|
+
"&[data-swiping]": { transitionDuration: "[0ms]" },
|
|
51
|
+
_motionReduce: { transitionDuration: "[0ms]" },
|
|
45
52
|
},
|
|
46
53
|
// The sheet's width, plus the shell's padding and its 1px edge on each side.
|
|
47
54
|
variants: {
|
|
48
55
|
size: {
|
|
49
56
|
// The assistant and a preview.
|
|
50
57
|
narrow: {
|
|
51
|
-
width: "min(100vw, calc(token(sizes.overlay.sheetNarrow) + token(spacing.panel.compact) * 2 + 2px))",
|
|
52
|
-
_phone: { width: "100vw" },
|
|
58
|
+
width: "[min(100vw, calc(token(sizes.overlay.sheetNarrow) + token(spacing.panel.compact) * 2 + 2px))]",
|
|
59
|
+
_phone: { width: "[100vw]" },
|
|
53
60
|
},
|
|
54
61
|
// Create, edit and act.
|
|
55
62
|
regular: {
|
|
56
|
-
width: "min(100vw, calc(token(sizes.overlay.sheet) + token(spacing.panel.compact) * 2 + 2px))",
|
|
57
|
-
_phone: { width: "100vw" },
|
|
63
|
+
width: "[min(100vw, calc(token(sizes.overlay.sheet) + token(spacing.panel.compact) * 2 + 2px))]",
|
|
64
|
+
_phone: { width: "[100vw]" },
|
|
58
65
|
},
|
|
59
66
|
// Near the full viewport, for content such as logs that needs the room.
|
|
60
|
-
large: { width: "calc(100vw - token(spacing.layout.pageGap) * 2)" },
|
|
67
|
+
large: { width: "[calc(100vw - token(spacing.layout.pageGap) * 2)]" },
|
|
61
68
|
},
|
|
62
69
|
},
|
|
63
70
|
defaultVariants: { size: "regular" },
|
|
@@ -74,7 +81,7 @@ const panel = css({
|
|
|
74
81
|
background: "bg.drawerSheet",
|
|
75
82
|
boxShadow: "soft",
|
|
76
83
|
color: "fg.primary",
|
|
77
|
-
_phone: { border: "0", borderRadius: "
|
|
84
|
+
_phone: { border: "0", borderRadius: "none" },
|
|
78
85
|
});
|
|
79
86
|
// At least the app header's height, so on a desktop a title-only sheet's header rule lines up with
|
|
80
87
|
// the main panel's beside it: both start one shell gap from the window's top. Under a subtitle it
|
|
@@ -137,8 +144,7 @@ const subtitleStyle = css({
|
|
|
137
144
|
letterSpacing: "compact",
|
|
138
145
|
lineHeight: "tight",
|
|
139
146
|
});
|
|
140
|
-
// The sheet's mark
|
|
141
|
-
// so the heading stays the title's line high rather than an inline box's.
|
|
147
|
+
// The sheet's mark is a flex row of its own, so the heading stays the title's line high rather than an inline box's.
|
|
142
148
|
const titleMark = css({
|
|
143
149
|
display: "flex",
|
|
144
150
|
alignItems: "center",
|
|
@@ -199,16 +205,35 @@ const footerActions = css({ display: "flex", alignItems: "center", gap: "layout.
|
|
|
199
205
|
/**
|
|
200
206
|
* A sheet docked at the window's right edge beside the page, which stays usable: it is not modal
|
|
201
207
|
* and a click outside leaves it open, so Escape or its close button closes it. Pass `modal` or
|
|
202
|
-
* `disablePointerDismissal` to change either.
|
|
208
|
+
* `disablePointerDismissal` to change either. Closing gives the focus back to what had it when
|
|
209
|
+
* `open` turned on, such as a button outside the drawer or the page link a hotkey opened it from.
|
|
203
210
|
*/
|
|
204
211
|
export function Drawer({ title, icon: titleIcon, eyebrow, subtitle, titleAccessory, actions, size = "regular", children, ...rootProps }) {
|
|
205
212
|
const { labels, dir } = useCiridaeLocale();
|
|
213
|
+
const popupRef = useRef(null);
|
|
214
|
+
const focusedBeforeOpen = useRef(null);
|
|
215
|
+
useLayoutEffect(() => {
|
|
216
|
+
if (!rootProps.open)
|
|
217
|
+
return;
|
|
218
|
+
const active = document.activeElement;
|
|
219
|
+
focusedBeforeOpen.current =
|
|
220
|
+
active instanceof HTMLElement && !popupRef.current?.contains(active) ? active : null;
|
|
221
|
+
}, [rootProps.open]);
|
|
222
|
+
// Back where it was, unless something outside has taken it since, such as a field on the page.
|
|
223
|
+
const returnFocus = () => {
|
|
224
|
+
const active = document.activeElement;
|
|
225
|
+
const takenOver = active instanceof HTMLElement &&
|
|
226
|
+
active !== document.body &&
|
|
227
|
+
!popupRef.current?.contains(active);
|
|
228
|
+
const before = focusedBeforeOpen.current;
|
|
229
|
+
return !takenOver && before?.isConnected ? before : true;
|
|
230
|
+
};
|
|
206
231
|
// The narrow sheet's title is body size, as the app header's is, beside a 34px close.
|
|
207
232
|
const narrow = size === "narrow";
|
|
208
233
|
const titleClassName = cx(heading({ size: narrow ? "small" : "medium" }), titleStyle);
|
|
209
234
|
const close = (_jsx(BaseDrawer.Close, { render: _jsx(IconButton, { "aria-label": labels.common.close, size: narrow ? "medium" : "small" }), children: _jsx(XIcon, { className: icon({ size: "small" }) }) }));
|
|
210
235
|
const titleContent = titleIcon ? (_jsxs("span", { className: titleMark, children: [titleIcon, title] })) : (title);
|
|
211
|
-
return (_jsx(BaseDrawer.Root, { modal: false, disablePointerDismissal: true, ...rootProps, swipeDirection: dir === "rtl" ? "left" : "right", children: _jsx(BaseDrawer.Portal, { children: _jsx(HotkeyLayer, { children: _jsx(BaseDrawer.Viewport, { className: viewport, children: _jsx(BaseDrawer.Popup, { className: popup({ size }), "data-ciridae-ui": "", children: _jsxs("div", { className: panel, children: [_jsx("header", { className: header({ size }), children: eyebrow ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: eyebrowLine, children: [eyebrow, _jsxs("div", { className: headerActions, children: [actions, close] })] }), _jsxs("div", { className: css({ display: "grid", gap: "layout.controlGap" }), children: [_jsx(BaseDrawer.Title, { className: displayTitle, children:
|
|
236
|
+
return (_jsx(BaseDrawer.Root, { modal: false, disablePointerDismissal: true, ...rootProps, swipeDirection: dir === "rtl" ? "left" : "right", children: _jsx(BaseDrawer.Portal, { children: _jsx(HotkeyLayer, { children: _jsx(BaseDrawer.Viewport, { className: viewport, children: _jsx(BaseDrawer.Popup, { ref: popupRef, className: popup({ size }), "data-ciridae-ui": "", finalFocus: returnFocus, children: _jsxs("div", { className: panel, children: [_jsx("header", { className: header({ size }), children: eyebrow ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: eyebrowLine, children: [eyebrow, _jsxs("div", { className: headerActions, children: [actions, close] })] }), _jsxs("div", { className: css({ display: "grid", gap: "layout.controlGap" }), children: [titleAccessory ? (_jsxs("div", { className: titleLine, children: [_jsx(BaseDrawer.Title, { className: displayTitle, children: titleContent }), titleAccessory] })) : (_jsx(BaseDrawer.Title, { className: displayTitle, children: titleContent })), subtitle && _jsx("p", { className: displaySubtitle, children: subtitle })] })] })) : (_jsxs("div", { className: headerLine({ size }), "data-header-line": "", children: [_jsxs("div", { className: titleBlock, children: [titleAccessory ? (_jsxs("div", { className: titleLine, children: [_jsx(BaseDrawer.Title, { className: titleClassName, children: titleContent }), titleAccessory] })) : (_jsx(BaseDrawer.Title, { className: titleClassName, children: titleContent })), subtitle && (_jsx("p", { className: subtitleStyle, "data-sheet-subtitle": "", children: subtitle }))] }), _jsxs("div", { className: headerActions, children: [actions, close] })] })) }), children] }) }) }) }) }) }));
|
|
212
237
|
}
|
|
213
238
|
export function DrawerBody({ flush = false, className, ...props }) {
|
|
214
239
|
return (_jsx(BaseDrawer.Content, { ...props, className: cx(body({ flush }), className), "data-ciridae-ui": "" }));
|
|
@@ -16,12 +16,12 @@ const zone = css({ position: "relative" });
|
|
|
16
16
|
// While files are over it, the zone dims under a dashed frame that names what a drop does.
|
|
17
17
|
const dropOverlay = css({
|
|
18
18
|
position: "absolute",
|
|
19
|
-
inset: "
|
|
19
|
+
inset: "none",
|
|
20
20
|
zIndex: "raised",
|
|
21
21
|
display: "grid",
|
|
22
22
|
placeItems: "center",
|
|
23
23
|
padding: "layout.controlGap",
|
|
24
|
-
background: "color-mix(in srgb, token(colors.bg.surface) 88%, transparent)",
|
|
24
|
+
background: "[color-mix(in srgb, token(colors.bg.surface) 88%, transparent)]",
|
|
25
25
|
pointerEvents: "none",
|
|
26
26
|
"& > span": {
|
|
27
27
|
display: "flex",
|
|
@@ -29,8 +29,8 @@ const dropOverlay = css({
|
|
|
29
29
|
alignItems: "center",
|
|
30
30
|
justifyContent: "center",
|
|
31
31
|
gap: "layout.controlGap",
|
|
32
|
-
width: "
|
|
33
|
-
height: "
|
|
32
|
+
width: "full",
|
|
33
|
+
height: "full",
|
|
34
34
|
border: "1px dashed token(colors.border.selected)",
|
|
35
35
|
borderRadius: "action",
|
|
36
36
|
background: "bg.selected",
|
|
@@ -56,7 +56,7 @@ const pad = css({
|
|
|
56
56
|
fontSize: "caption",
|
|
57
57
|
fontWeight: "medium",
|
|
58
58
|
letterSpacing: "compact",
|
|
59
|
-
transitionProperty: "border-color, color",
|
|
59
|
+
transitionProperty: "[border-color, color]",
|
|
60
60
|
transitionDuration: "fast",
|
|
61
61
|
"& > svg": { flexShrink: "0" },
|
|
62
62
|
_hover: { borderColor: "border.selected", color: "fg.secondary" },
|
|
@@ -99,8 +99,8 @@ const fileMark = css({
|
|
|
99
99
|
height: "control.mark",
|
|
100
100
|
color: "fg.muted",
|
|
101
101
|
"& img": {
|
|
102
|
-
width: "
|
|
103
|
-
height: "
|
|
102
|
+
width: "full",
|
|
103
|
+
height: "full",
|
|
104
104
|
objectFit: "cover",
|
|
105
105
|
borderRadius: "control",
|
|
106
106
|
},
|
|
@@ -140,10 +140,10 @@ export const fileSquare = css({
|
|
|
140
140
|
fontSize: "avatar.small",
|
|
141
141
|
lineHeight: "compact",
|
|
142
142
|
textAlign: "center",
|
|
143
|
-
"& > img": { display: "block", width: "
|
|
143
|
+
"& > img": { display: "block", width: "full", height: "full", objectFit: "cover" },
|
|
144
144
|
"&[data-image]": { padding: "none", background: "bg.fill" },
|
|
145
145
|
"& > span": {
|
|
146
|
-
maxWidth: "
|
|
146
|
+
maxWidth: "full",
|
|
147
147
|
overflow: "hidden",
|
|
148
148
|
textOverflow: "ellipsis",
|
|
149
149
|
whiteSpace: "nowrap",
|
|
@@ -185,10 +185,10 @@ const fileChip = css({
|
|
|
185
185
|
display: "inline-flex",
|
|
186
186
|
alignItems: "center",
|
|
187
187
|
gap: "layout.tightGap",
|
|
188
|
-
maxWidth: "
|
|
188
|
+
maxWidth: "full",
|
|
189
189
|
height: "control.shortcut",
|
|
190
190
|
paddingInlineStart: "control.trackInset",
|
|
191
|
-
paddingInlineEnd: "1px",
|
|
191
|
+
paddingInlineEnd: "[1px]",
|
|
192
192
|
border: "1px solid token(colors.border.subtle)",
|
|
193
193
|
borderRadius: "control",
|
|
194
194
|
background: "bg.card",
|
|
@@ -206,8 +206,8 @@ const fileChip = css({
|
|
|
206
206
|
},
|
|
207
207
|
"& > [data-mark] > svg": { fontSize: "icon.compact" },
|
|
208
208
|
"& > [data-mark] > img": {
|
|
209
|
-
width: "
|
|
210
|
-
height: "
|
|
209
|
+
width: "full",
|
|
210
|
+
height: "full",
|
|
211
211
|
objectFit: "cover",
|
|
212
212
|
borderRadius: "control",
|
|
213
213
|
},
|
|
@@ -65,18 +65,14 @@ export type EditableFieldProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
65
65
|
badge?: ReactNode;
|
|
66
66
|
/** Under the value while the row is idle. */
|
|
67
67
|
note?: ReactNode;
|
|
68
|
-
/**
|
|
68
|
+
/** With `emphasis="highlighted"` the row keeps the yellow band. */
|
|
69
69
|
action?: {
|
|
70
70
|
label: ReactNode;
|
|
71
71
|
onClick: () => void;
|
|
72
72
|
disabled?: boolean;
|
|
73
73
|
};
|
|
74
|
-
/** `bottom` by default; `none` for the last row of a list whose container draws its own edge. */
|
|
75
74
|
divider?: "bottom" | "none";
|
|
76
|
-
/**
|
|
77
|
-
* `selected` washes the row with the selected glass, such as the field a side panel is
|
|
78
|
-
* showing; `inset` sets it into the list between hairlines, such as a field set apart.
|
|
79
|
-
*/
|
|
75
|
+
/** `highlighted` is the yellow band while the agent points at the field. */
|
|
80
76
|
emphasis?: "selected" | "inset" | "highlighted";
|
|
81
77
|
edit?: FieldEdit;
|
|
82
78
|
labels?: Partial<CiridaeLabels["editableField"]>;
|
|
@@ -99,7 +95,6 @@ export type SourceConflictProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
99
95
|
};
|
|
100
96
|
/** At the effective row's end, such as a Resolve button. */
|
|
101
97
|
action?: ReactNode;
|
|
102
|
-
/** `highlighted` while the agent points at the field; `neutral` by default. */
|
|
103
98
|
tone?: "highlighted" | "neutral";
|
|
104
99
|
labels?: Partial<{
|
|
105
100
|
effectiveValue: string;
|
|
@@ -19,12 +19,6 @@ import { Tooltip } from "./overlays.js";
|
|
|
19
19
|
import { Combobox } from "./select.js";
|
|
20
20
|
/* The row stacks its label over the value in a narrow box, so each field is its own container. */
|
|
21
21
|
const fieldBox = css({ containerType: "inline-size" });
|
|
22
|
-
/*
|
|
23
|
-
* The kit's Detail field: 12 · 16 padding, a hairline under it. A field that needs the reader
|
|
24
|
-
* (the inline edit's Needs confirm) and an inset row wear the selected glass between the selected
|
|
25
|
-
* edge's hairlines; a selected row wears the glass alone; a highlighted row, while the agent points
|
|
26
|
-
* at it, is the flat yellow band between hairlines.
|
|
27
|
-
*/
|
|
28
22
|
const fieldRow = css({
|
|
29
23
|
position: "relative",
|
|
30
24
|
display: "grid",
|
|
@@ -39,28 +33,27 @@ const fieldRow = css({
|
|
|
39
33
|
letterSpacing: "compact",
|
|
40
34
|
"& > :last-child": { alignSelf: "center" },
|
|
41
35
|
"&[data-needs]": {
|
|
42
|
-
background: "token(gradients.selected)",
|
|
36
|
+
background: "[token(gradients.selected)]",
|
|
43
37
|
borderBlock: "1px solid",
|
|
44
38
|
borderImage: "token(gradients.border.selected) 1",
|
|
45
39
|
},
|
|
46
40
|
// After the band's hairlines, so a last highlighted row keeps only its top one, as the kit's.
|
|
47
41
|
"&[data-divider=none]": { borderBottom: "0" },
|
|
48
|
-
"&[data-emphasis=selected]": { background: "token(gradients.selected)" },
|
|
42
|
+
"&[data-emphasis=selected]": { background: "[token(gradients.selected)]" },
|
|
49
43
|
"&[data-emphasis=inset]": {
|
|
50
|
-
background: "token(gradients.selected)",
|
|
44
|
+
background: "[token(gradients.selected)]",
|
|
51
45
|
borderBlock: "1px solid",
|
|
52
46
|
borderImage: "token(gradients.border.selected) 1",
|
|
53
47
|
},
|
|
54
|
-
// The kit's Highlighted detail field: the yellow band while the agent points at the field.
|
|
55
48
|
"&[data-emphasis=highlighted]": {
|
|
56
49
|
background: "bg.warningTint",
|
|
57
50
|
borderBlock: "1px solid token(colors.border.divider)",
|
|
58
51
|
},
|
|
59
52
|
"&[data-editable]": {
|
|
60
53
|
cursor: "pointer",
|
|
61
|
-
_hover: { background: "token(gradients.card)", _light: { background: "bg.rowHover" } },
|
|
54
|
+
_hover: { background: "[token(gradients.card)]", _light: { background: "bg.rowHover" } },
|
|
62
55
|
},
|
|
63
|
-
"&[data-editable]:is(:hover, :focus-within) [data-affordance], &[data-editing] [data-affordance]": { opacity: "1" },
|
|
56
|
+
"&[data-editable]:is(:hover, :focus-within) [data-affordance], &[data-editing] [data-affordance]": { opacity: "[1]" },
|
|
64
57
|
"@container (max-width: 520px)": {
|
|
65
58
|
gridTemplateColumns: "minmax(0, 1fr) auto",
|
|
66
59
|
rowGap: "layout.tightGap",
|
|
@@ -91,7 +84,7 @@ const valueButton = css({
|
|
|
91
84
|
border: "0",
|
|
92
85
|
borderRadius: "control",
|
|
93
86
|
background: "transparent",
|
|
94
|
-
color: "inherit",
|
|
87
|
+
color: "[inherit]",
|
|
95
88
|
font: "inherit",
|
|
96
89
|
textAlign: "start",
|
|
97
90
|
cursor: "pointer",
|
|
@@ -99,8 +92,8 @@ const valueButton = css({
|
|
|
99
92
|
});
|
|
100
93
|
const affordance = css({
|
|
101
94
|
color: "fg.muted",
|
|
102
|
-
opacity: "0",
|
|
103
|
-
transitionProperty: "opacity",
|
|
95
|
+
opacity: "[0]",
|
|
96
|
+
transitionProperty: "[opacity]",
|
|
104
97
|
transitionDuration: "fast",
|
|
105
98
|
});
|
|
106
99
|
const lockMark = css({ display: "inline-flex", color: "fg.muted" });
|
|
@@ -143,7 +136,7 @@ const sourceLink = css({
|
|
|
143
136
|
padding: "none",
|
|
144
137
|
border: "0",
|
|
145
138
|
background: "transparent",
|
|
146
|
-
color: "inherit",
|
|
139
|
+
color: "[inherit]",
|
|
147
140
|
font: "inherit",
|
|
148
141
|
cursor: "pointer",
|
|
149
142
|
textAlign: "start",
|
|
@@ -161,20 +154,19 @@ const fieldNote = css({
|
|
|
161
154
|
fontWeight: "medium",
|
|
162
155
|
lineHeight: "tight",
|
|
163
156
|
});
|
|
164
|
-
const editor = css({ width: "200px", maxWidth: "
|
|
157
|
+
const editor = css({ width: "[200px]", maxWidth: "full" });
|
|
165
158
|
const editorValue = css({ position: "relative", display: "flex", alignItems: "center" });
|
|
166
159
|
const tooltipTitle = css({ display: "block", fontWeight: "medium" });
|
|
167
|
-
const tooltipDetail = css({ display: "block", fontSize: "code", opacity: "0.8" });
|
|
160
|
+
const tooltipDetail = css({ display: "block", fontSize: "code", opacity: "[0.8]" });
|
|
168
161
|
const trailingActions = css({ display: "inline-flex", gap: "layout.tightGap" });
|
|
169
162
|
/* The calendar opens above the date editor, on the menus' glass sheet. */
|
|
170
163
|
const calendarPicker = css(glassMenuSurface, {
|
|
171
164
|
position: "absolute",
|
|
172
|
-
bottom: "calc(100% + token(spacing.control.iconGap))",
|
|
173
|
-
insetInlineStart: "
|
|
165
|
+
bottom: "[calc(100% + token(spacing.control.iconGap))]",
|
|
166
|
+
insetInlineStart: "none",
|
|
174
167
|
zIndex: "popover",
|
|
175
168
|
cursor: "default",
|
|
176
169
|
});
|
|
177
|
-
// Under the days, inset as the calendar is, such as the value it had before.
|
|
178
170
|
const calendarFooter = css({
|
|
179
171
|
paddingInline: "panel.compact",
|
|
180
172
|
paddingBottom: "panel.compact",
|
|
@@ -388,13 +380,8 @@ export function EditableField({ label, value, provenance, badge, note, action, d
|
|
|
388
380
|
}
|
|
389
381
|
return _jsx("span", {});
|
|
390
382
|
};
|
|
391
|
-
return (_jsx("div", { ...props, className: cx(fieldBox, className), "data-ciridae-ui": "", children: _jsxs("div", { ref: rowRef, className: fieldRow, "data-needs": action && !editing ? "" : undefined, "data-divider": divider, "data-emphasis": emphasis, "data-editable": editable && !editing ? "" : undefined, "data-editing": editing ? "" : undefined, onClick: begin, children: [_jsx("span", { className: fieldLabel, id: labelId, "data-label": "", children: label }), _jsxs("span", { className: css({ minWidth: "0" }), children: [valueLine(), _jsx("span", { role: "status", children: statusLine() }), note !== undefined && status.mode === "idle" && (_jsx("span", { className: fieldNote, children: note }))] }), trailing()] }) }));
|
|
383
|
+
return (_jsx("div", { ...props, className: cx(fieldBox, className), "data-ciridae-ui": "", children: _jsxs("div", { ref: rowRef, className: fieldRow, "data-needs": action && !editing && emphasis !== "highlighted" ? "" : undefined, "data-divider": divider, "data-emphasis": emphasis, "data-editable": editable && !editing ? "" : undefined, "data-editing": editing ? "" : undefined, onClick: begin, children: [_jsx("span", { className: fieldLabel, id: labelId, "data-label": "", children: label }), _jsxs("span", { className: css({ minWidth: "0" }), children: [valueLine(), _jsx("span", { role: "status", children: statusLine() }), note !== undefined && status.mode === "idle" && (_jsx("span", { className: fieldNote, children: note }))] }), trailing()] }) }));
|
|
392
384
|
}
|
|
393
|
-
/*
|
|
394
|
-
* Source conflict: each source's value under a disputed field, then the value in effect. The
|
|
395
|
-
* kit's Contested sources: flat and square between hairlines, the yellow band while the agent
|
|
396
|
-
* points at the field, the panel's face otherwise (the grey well in light).
|
|
397
|
-
*/
|
|
398
385
|
const conflictBlock = css({
|
|
399
386
|
display: "grid",
|
|
400
387
|
gap: "layout.controlGap",
|
|
@@ -2,7 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { css, cx } from "#primitives/css";
|
|
3
3
|
import { Chip } from "./chip.js";
|
|
4
4
|
import { useFieldControl } from "./field-context.js";
|
|
5
|
-
// The field face `Input` wears, holding chips that wrap onto more lines as they fill it.
|
|
6
5
|
const emailField = css({
|
|
7
6
|
display: "flex",
|
|
8
7
|
flexWrap: "wrap",
|
|
@@ -28,9 +27,9 @@ const draftInput = css({
|
|
|
28
27
|
fontSize: "caption",
|
|
29
28
|
height: "control.shortcut",
|
|
30
29
|
paddingInline: "control.compactInline",
|
|
31
|
-
outline: "
|
|
30
|
+
outline: "0",
|
|
32
31
|
_placeholder: { color: "fg.subtle" },
|
|
33
|
-
_focusVisible: { outline: "
|
|
32
|
+
_focusVisible: { outline: "0", boxShadow: "[none]" },
|
|
34
33
|
});
|
|
35
34
|
/** Comma, semicolon, whitespace, Enter, Tab, or blur commits addresses; duplicates are ignored. */
|
|
36
35
|
export function EmailInput({ value, onValueChange, inputValue, onInputValueChange, invalidEmails = [], disabled, className, onKeyDown, onBlur, onPaste, ...props }) {
|
|
@@ -6,31 +6,31 @@ import { SiteBanner } from "./site-banner.js";
|
|
|
6
6
|
const frame = css({
|
|
7
7
|
display: "flex",
|
|
8
8
|
flexDirection: "column",
|
|
9
|
-
height: "100dvh",
|
|
10
|
-
width: "
|
|
9
|
+
height: "[100dvh]",
|
|
10
|
+
width: "full",
|
|
11
11
|
});
|
|
12
12
|
const environmentBanner = css({
|
|
13
13
|
// Align with the outer edges of the sidebar controls, not their inset labels.
|
|
14
|
-
paddingInlineStart: "calc(token(spacing.panel.compact) + token(spacing.panel.default))",
|
|
14
|
+
paddingInlineStart: "[calc(token(spacing.panel.compact) + token(spacing.panel.default))]",
|
|
15
15
|
_phone: { paddingInlineStart: "panel.default" },
|
|
16
16
|
});
|
|
17
17
|
const viewport = css({
|
|
18
18
|
flex: "1",
|
|
19
19
|
minHeight: "0",
|
|
20
20
|
overflow: "hidden",
|
|
21
|
-
background: "token(gradients.canvas)",
|
|
21
|
+
background: "[token(gradients.canvas)]",
|
|
22
22
|
// Only under the environment strip does the app read as inset below it.
|
|
23
23
|
"&[data-under-banner]": {
|
|
24
24
|
borderTopRadius: "field",
|
|
25
|
-
boxShadow: "inset 0 2px 4px rgba(0, 0, 0, 0.18)",
|
|
25
|
+
boxShadow: "[inset 0 2px 4px rgba(0, 0, 0, 0.18)]",
|
|
26
26
|
},
|
|
27
27
|
// Keep the shell and its phone layout within the space below the site banner. On a desktop the
|
|
28
28
|
// shell's row sizes the main panel inside its block margins, so a full height would push it past
|
|
29
29
|
// them; a phone's main panel is a full window tall, so there it takes the space under the strip.
|
|
30
|
-
"& > [data-ciridae-ui]": { height: "
|
|
30
|
+
"& > [data-ciridae-ui]": { height: "full", background: "transparent" },
|
|
31
31
|
"& > [data-ciridae-ui] > main": {
|
|
32
32
|
borderRadius: "inset",
|
|
33
|
-
_phone: { borderRadius: "
|
|
33
|
+
_phone: { borderRadius: "none", height: "full" },
|
|
34
34
|
},
|
|
35
35
|
"& > [data-ciridae-ui] > main > header": {
|
|
36
36
|
paddingInlineStart: "page.inline",
|
|
@@ -12,10 +12,10 @@ const collapsedWrapper = css({
|
|
|
12
12
|
const expandedWrapper = css({ display: "grid", justifyItems: "start", minWidth: "0" });
|
|
13
13
|
const clamped = css({ lineClamp: "2", minWidth: "0" });
|
|
14
14
|
const toggle = css({
|
|
15
|
-
padding: "
|
|
15
|
+
padding: "none",
|
|
16
16
|
border: "0",
|
|
17
17
|
background: "transparent",
|
|
18
|
-
color: "inherit",
|
|
18
|
+
color: "[inherit]",
|
|
19
19
|
font: "inherit",
|
|
20
20
|
textDecoration: "underline",
|
|
21
21
|
whiteSpace: "nowrap",
|