@ciridae/ui 1.0.2 → 1.0.4
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/app/auth.d.ts +10 -0
- package/dist/app/auth.js +60 -0
- package/dist/app/error-boundary.d.ts +18 -0
- package/dist/app/error-boundary.js +45 -0
- package/dist/app/feedback.d.ts +12 -0
- package/dist/app/feedback.js +128 -0
- package/dist/app/index.d.ts +8 -0
- package/dist/app/index.js +8 -0
- package/dist/app/request-errors.d.ts +63 -0
- package/dist/app/request-errors.js +172 -0
- package/dist/app/sentry.d.ts +18 -0
- package/dist/app/sentry.js +52 -0
- package/dist/app/telemetry.d.ts +7 -0
- package/dist/app/telemetry.js +28 -0
- package/dist/app/trail.d.ts +9 -0
- package/dist/app/trail.js +18 -0
- package/dist/chat/chat-query-keys.d.ts +3 -3
- package/dist/chat/contract.d.ts +15 -15
- package/dist/chat/conversation-items-query-options.d.ts +114 -114
- package/dist/chat/conversation-source.d.ts +89 -0
- package/dist/chat/conversation-source.js +1 -0
- package/dist/chat/describe-tool-call.d.ts +3 -3
- package/dist/chat/describe-tool-call.js +3 -3
- package/dist/chat/message-text.d.ts +1 -1
- package/dist/chat/message-text.js +116 -48
- package/dist/chat/use-conversation-list.d.ts +6 -6
- package/dist/ciridae.css +16 -4
- package/dist/components/activity-feed.d.ts +3 -2
- package/dist/components/activity-feed.js +1 -0
- package/dist/components/agent-work.d.ts +3 -3
- package/dist/components/app-frame.d.ts +91 -0
- package/dist/components/app-frame.js +134 -0
- package/dist/components/app-navigation.d.ts +30 -3
- package/dist/components/app-navigation.js +105 -14
- package/dist/components/badge.d.ts +30 -5
- package/dist/components/badge.js +134 -15
- package/dist/components/brand-icons.d.ts +3 -3
- package/dist/components/bulk-action-bar.d.ts +1 -1
- package/dist/components/bulk-action-bar.js +3 -3
- package/dist/components/button.d.ts +12 -5
- package/dist/components/button.js +77 -44
- package/dist/components/calendar.d.ts +1 -1
- package/dist/components/calendar.js +44 -17
- package/dist/components/centered-page.d.ts +1 -1
- package/dist/components/centered-page.js +2 -2
- package/dist/components/chart.d.ts +22 -2
- package/dist/components/chart.js +251 -51
- package/dist/components/chat-client-source.d.ts +16 -0
- package/dist/components/chat-client-source.js +297 -0
- package/dist/components/chat-page.d.ts +9 -8
- package/dist/components/chat-page.js +7 -11
- package/dist/components/chat-sheet-controller.d.ts +11 -14
- package/dist/components/chat-sheet-controller.js +3 -3
- package/dist/components/chat-sheet.d.ts +18 -11
- package/dist/components/chat-sheet.js +188 -289
- package/dist/components/chat.d.ts +109 -19
- package/dist/components/chat.js +520 -124
- package/dist/components/checkbox-item.d.ts +6 -3
- package/dist/components/checkbox-item.js +9 -5
- package/dist/components/checkbox-list.d.ts +1 -1
- package/dist/components/chip.d.ts +6 -1
- package/dist/components/chip.js +27 -1
- package/dist/components/collapsible.d.ts +1 -1
- package/dist/components/color-theme.d.ts +1 -1
- package/dist/components/column-settings.d.ts +1 -1
- package/dist/components/column-settings.js +1 -1
- package/dist/components/command-menu.d.ts +5 -1
- package/dist/components/command-menu.js +98 -32
- package/dist/components/command-palette.d.ts +7 -3
- package/dist/components/command-palette.js +20 -11
- package/dist/components/copyable-id.d.ts +22 -5
- package/dist/components/copyable-id.js +46 -6
- package/dist/components/data-display.d.ts +39 -8
- package/dist/components/data-display.js +138 -19
- package/dist/components/data-grid.d.ts +23 -11
- package/dist/components/data-grid.js +61 -26
- package/dist/components/date-range-picker.d.ts +1 -1
- package/dist/components/date-range-picker.js +9 -20
- package/dist/components/date-time.d.ts +1 -1
- package/dist/components/dialog-height-context.d.ts +1 -1
- package/dist/components/document-viewer.d.ts +2 -2
- package/dist/components/drawer.d.ts +11 -6
- package/dist/components/drawer.js +91 -54
- package/dist/components/dropzone.d.ts +4 -4
- package/dist/components/editable-field.d.ts +12 -3
- package/dist/components/editable-field.js +57 -27
- package/dist/components/email-input.d.ts +1 -1
- package/dist/components/email-input.js +6 -5
- package/dist/components/environment-frame.d.ts +2 -2
- package/dist/components/environment-frame.js +37 -6
- package/dist/components/expandable-text.d.ts +1 -1
- package/dist/components/feedback-screenshot.d.ts +1 -1
- package/dist/components/feedback-sheet.d.ts +18 -3
- package/dist/components/feedback-sheet.js +216 -55
- package/dist/components/field-context.d.ts +1 -1
- package/dist/components/filter-bar.d.ts +3 -3
- package/dist/components/filter-bar.js +43 -29
- package/dist/components/form-controls.d.ts +12 -3
- package/dist/components/form-controls.js +46 -22
- package/dist/components/form-layout.d.ts +14 -10
- package/dist/components/form-layout.js +68 -23
- package/dist/components/glass-menu.d.ts +3 -0
- package/dist/components/glass-menu.js +63 -0
- package/dist/components/gradient-edge.d.ts +9 -0
- package/dist/components/gradient-edge.js +31 -0
- package/dist/components/hotkeys.d.ts +2 -2
- package/dist/components/icon.d.ts +1 -1
- package/dist/components/input.d.ts +7 -5
- package/dist/components/input.js +29 -17
- package/dist/components/keyboard-shortcuts.d.ts +2 -2
- package/dist/components/keycap.d.ts +10 -6
- package/dist/components/keycap.js +57 -19
- package/dist/components/layout.d.ts +13 -13
- package/dist/components/lightbox.d.ts +9 -3
- package/dist/components/lightbox.js +13 -9
- package/dist/components/link.d.ts +1 -1
- package/dist/components/locale.d.ts +42 -2
- package/dist/components/locale.js +43 -3
- package/dist/components/log-entry.d.ts +40 -0
- package/dist/components/log-entry.js +146 -0
- package/dist/components/log-list.d.ts +3 -3
- package/dist/components/mention-input.d.ts +2 -2
- package/dist/components/mention-input.js +4 -3
- package/dist/components/menu.d.ts +7 -3
- package/dist/components/menu.js +34 -37
- package/dist/components/meter.d.ts +10 -2
- package/dist/components/meter.js +64 -6
- package/dist/components/navigation.d.ts +21 -4
- package/dist/components/navigation.js +84 -19
- package/dist/components/notification-tray.d.ts +1 -1
- package/dist/components/notification-tray.js +5 -4
- package/dist/components/overlays.d.ts +6 -4
- package/dist/components/overlays.js +69 -40
- package/dist/components/page-frame.d.ts +4 -4
- package/dist/components/page-frame.js +1 -1
- package/dist/components/panel.d.ts +4 -4
- package/dist/components/panel.js +18 -12
- package/dist/components/profile-header.d.ts +1 -1
- package/dist/components/progress.d.ts +1 -1
- package/dist/components/project-avatar.d.ts +1 -1
- package/dist/components/radio-card.d.ts +2 -2
- package/dist/components/radio-card.js +10 -9
- package/dist/components/record.d.ts +29 -5
- package/dist/components/record.js +147 -18
- package/dist/components/resolved-file-url.d.ts +19 -0
- package/dist/components/resolved-file-url.js +49 -0
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/secret-dialog.d.ts +1 -1
- package/dist/components/segmented-bar.d.ts +4 -2
- package/dist/components/segmented-bar.js +16 -6
- package/dist/components/select.d.ts +9 -6
- package/dist/components/select.js +103 -127
- package/dist/components/settings.d.ts +4 -4
- package/dist/components/shell-skeleton.d.ts +1 -1
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +21 -21
- package/dist/components/shell.js +43 -43
- package/dist/components/side-panel.d.ts +3 -3
- package/dist/components/sidebar.d.ts +13 -8
- package/dist/components/sidebar.js +55 -27
- package/dist/components/single-line-text.d.ts +2 -0
- package/dist/components/single-line-text.js +16 -0
- package/dist/components/site-banner.d.ts +5 -2
- package/dist/components/site-banner.js +17 -6
- package/dist/components/skeleton.d.ts +8 -7
- package/dist/components/skeleton.js +28 -16
- package/dist/components/skeletons.d.ts +17 -5
- package/dist/components/skeletons.js +71 -8
- package/dist/components/stages.d.ts +83 -11
- package/dist/components/stages.js +512 -156
- package/dist/components/stat-card.d.ts +12 -4
- package/dist/components/stat-card.js +92 -37
- package/dist/components/status-banner.d.ts +1 -1
- package/dist/components/status-banner.js +1 -1
- package/dist/components/status.d.ts +2 -2
- package/dist/components/steps.d.ts +1 -1
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/tabs.d.ts +8 -8
- package/dist/components/tabs.js +26 -13
- package/dist/components/theme-customizer.d.ts +2 -2
- package/dist/components/theme-toggle.d.ts +4 -0
- package/dist/components/theme-toggle.js +67 -0
- package/dist/components/toast.d.ts +10 -3
- package/dist/components/toast.js +78 -29
- package/dist/components/use-new-version-available.d.ts +6 -0
- package/dist/components/use-new-version-available.js +29 -0
- package/dist/components/user-chip.d.ts +3 -3
- package/dist/components/wizard.d.ts +2 -2
- package/dist/feedback/contract.d.ts +136 -136
- package/dist/feedback/feedback-controller.d.ts +6 -6
- package/dist/feedback/generated/zod.gen.d.ts +28 -28
- package/dist/feedback/operator-contract.d.ts +11 -11
- package/dist/feedback/operator-controller.d.ts +32 -13
- package/dist/feedback/operator-controller.js +44 -11
- package/dist/preset.js +289 -33
- package/dist/styled-system/styles.css +3294 -1079
- package/dist/styled-system/tokens/index.mjs +598 -22
- package/dist/styled-system/tokens/tokens.d.ts +11 -11
- package/dist/styled-system/types/prop-type.d.ts +2 -2
- package/dist/styles.css +16 -4
- package/dist/theme/color.d.ts +3 -0
- package/dist/theme/color.js +5 -0
- package/dist/theme/derive.d.ts +9 -2
- package/dist/theme/derive.js +72 -12
- package/dist/theme/palettes.d.ts +49 -6
- package/dist/theme/palettes.js +84 -15
- package/dist/theme/tokens.d.ts +3 -3
- package/dist/theme/tokens.js +107 -32
- package/package.json +40 -3
|
@@ -61,7 +61,7 @@ function scrollingAncestor(element) {
|
|
|
61
61
|
* hover-revealed row actions, groups, loading, empty and no-results states. `role="table"`; Enter
|
|
62
62
|
* on a pressable row opens it.
|
|
63
63
|
*/
|
|
64
|
-
export function DataGrid({ data, columns, getRowId, variant = "framed", density = "default", sorting: sortingProp, defaultSorting = emptySorting, onSortingChange, manualSorting = false, enableRowSelection, rowSelection: rowSelectionProp, defaultRowSelection = emptySelection, onRowSelectionChange, stickySelectColumn = false, columnVisibility: columnVisibilityProp, defaultColumnVisibility = emptyVisibility, onColumnVisibilityChange, columnOrder: columnOrderProp, defaultColumnOrder = emptyOrder, onColumnOrderChange, headerMenu = false, filters, onFiltersChange, getRowHref, renderRowLink, onRowClick, activeRowId, keyboardNavigation = false, virtualize = false, rowActions, renderRowDetail, groupBy, renderGroupRow, loading = false, empty, noResults, filtered, hideHeader = false, fill = false, narrowScreenLayout = "columns", footer, labels: ownLabels, className, frameClassName, style, ...props }) {
|
|
64
|
+
export function DataGrid({ data, columns, getRowId, variant = "framed", density = "default", sorting: sortingProp, defaultSorting = emptySorting, onSortingChange, manualSorting = false, page, enableRowSelection, rowSelection: rowSelectionProp, defaultRowSelection = emptySelection, onRowSelectionChange, stickySelectColumn = false, columnVisibility: columnVisibilityProp, defaultColumnVisibility = emptyVisibility, onColumnVisibilityChange, columnOrder: columnOrderProp, defaultColumnOrder = emptyOrder, onColumnOrderChange, headerMenu = false, filters, onFiltersChange, getRowHref, renderRowLink, onRowClick, activeRowId, keyboardNavigation = false, virtualize = false, rowActions, renderRowDetail, groupBy, renderGroupRow, loading = false, empty, noResults, filtered, hideHeader = false, fill = false, narrowScreenLayout = "columns", footer, labels: ownLabels, className, frameClassName, style, ...props }) {
|
|
65
65
|
const { labels: localeLabels } = useCiridaeLocale();
|
|
66
66
|
const labels = { ...localeLabels.table, ...ownLabels };
|
|
67
67
|
const [sorting, setSorting] = useControllableState(sortingProp, defaultSorting, onSortingChange);
|
|
@@ -149,7 +149,10 @@ export function DataGrid({ data, columns, getRowId, variant = "framed", density
|
|
|
149
149
|
}
|
|
150
150
|
const selectable = enableRowSelection !== undefined && enableRowSelection !== false;
|
|
151
151
|
const canSelect = (row) => typeof enableRowSelection === "function" ? enableRowSelection(row) : selectable;
|
|
152
|
-
const
|
|
152
|
+
const sortedRows = table.getRowModel().rows;
|
|
153
|
+
const rows = page
|
|
154
|
+
? sortedRows.slice((page.number - 1) * page.rowsPerPage, page.number * page.rowsPerPage)
|
|
155
|
+
: sortedRows;
|
|
153
156
|
const selectableIds = rows.filter((row) => canSelect(row.original)).map((row) => row.id);
|
|
154
157
|
const setSelected = (ids, selected) => {
|
|
155
158
|
const next = Object.fromEntries(Object.entries(rowSelection).filter(([id]) => selected || !ids.includes(id)));
|
|
@@ -487,14 +490,12 @@ export function DataGrid({ data, columns, getRowId, variant = "framed", density
|
|
|
487
490
|
headRefs.current.set(column.id, element);
|
|
488
491
|
else
|
|
489
492
|
headRefs.current.delete(column.id);
|
|
490
|
-
}, children: menuItems.length > 0 ? (_jsx(Menu, { align: meta?.align === "end" ? "end" : "start", trigger: _jsxs("button", { type: "button", className: headButton, "data-sorted": sorted || undefined, children: [content, caret] }), items: menuItems })) : column.getCanSort() ? (_jsxs("button", { type: "button", className: headButton, "data-sorted": sorted || undefined,
|
|
493
|
+
}, children: menuItems.length > 0 ? (_jsx(Menu, { align: meta?.align === "end" ? "end" : "start", trigger: _jsxs("button", { type: "button", className: headButton, "data-sorted": sorted || undefined, children: [content, caret] }), items: menuItems })) : column.getCanSort() ? (_jsxs("button", { type: "button", className: headButton, "data-sorted": sorted || undefined, onClick: column.getToggleSortingHandler(), children: [content, caret] })) : (content) }, column.id));
|
|
491
494
|
};
|
|
492
495
|
const showEmpty = !loading && rows.length === 0;
|
|
493
496
|
const isFiltered = filtered ?? (filters !== undefined && filters.length > 0);
|
|
494
497
|
const emptyContent = isFiltered && noResults !== undefined ? noResults : (empty ?? labels.nothingToShow);
|
|
495
|
-
return (_jsxs("div", { ref: frameRef, className: cx(frame, frameClassName), "data-ciridae-ui": "", "data-variant": variant, "data-density": density, "data-fill": fill || undefined, "data-stacked": narrowScreenLayout === "stacked" || undefined, children: [_jsxs("div", { ...props, ref: gridRef, role: "table", "aria-busy": loading || undefined, className: cx(grid, className), style: { ...style, gridTemplateColumns: template }, children: [!hideHeader && (_jsxs("div", { role: "row", className: headRow, children: [selectable && (_jsx("div", { ref: selectHeadRef, role: "columnheader", className: cx(headCell, selectCell, stickySelectColumn && pinnedCell), children: _jsx(Checkbox, { "aria-label": labels.selectAll, checked: allSelected === "all" && selectableIds.length > 0, indeterminate: allSelected === "some", disabled: loading || selectableIds.length === 0, onCheckedChange: (checked) => setSelected(selectableIds, checked) }) })), shownColumns.map(headerCell), rowActions && (_jsx("div", { role: "columnheader", className: headCell, children: _jsx("span", { className: visuallyHidden, children: labels.actions }) }))] })), loading ? (skeletonRows.map((rowIndex) => (_jsxs("div", { role: "row", className: bodyRow, "data-skeleton": "", children: [selectable && _jsx("div", { role: "cell", className: cx(cell, selectCell) }), shownColumns.map((column, columnIndex) => (_jsx("div", { role: "cell", className: cellClass(column), "data-align": column.columnDef.meta?.align, children: column.columnDef.meta?.skeleton
|
|
496
|
-
width: skeletonWidths[(rowIndex + columnIndex) % skeletonWidths.length],
|
|
497
|
-
} })) }, column.id))), rowActions && _jsx("div", { role: "cell", className: cell })] }, rowIndex)))) : showEmpty ? (_jsx("div", { role: "row", className: emptyRow, children: _jsx("div", { role: "cell", "aria-colspan": columnCount, className: emptyCell, children: emptyContent }) })) : (drawBody())] }), footer, filterColumn && filterField && onFiltersChange && (_jsx(Popover, { open: true, onOpenChange: (open) => {
|
|
498
|
+
return (_jsxs("div", { ref: frameRef, className: cx(frame, frameClassName), "data-ciridae-ui": "", "data-variant": variant, "data-density": density, "data-fill": fill || undefined, "data-stacked": narrowScreenLayout === "stacked" || undefined, children: [_jsxs("div", { ...props, ref: gridRef, role: "table", "aria-busy": loading || undefined, className: cx(grid, className), style: { ...style, gridTemplateColumns: template }, children: [!hideHeader && (_jsxs("div", { role: "row", className: headRow, children: [selectable && (_jsx("div", { ref: selectHeadRef, role: "columnheader", className: cx(headCell, selectCell, stickySelectColumn && pinnedCell), children: _jsx(Checkbox, { "aria-label": labels.selectAll, checked: allSelected === "all" && selectableIds.length > 0, indeterminate: allSelected === "some", disabled: loading || selectableIds.length === 0, onCheckedChange: (checked) => setSelected(selectableIds, checked) }) })), shownColumns.map(headerCell), rowActions && (_jsx("div", { role: "columnheader", className: headCell, children: _jsx("span", { className: visuallyHidden, children: labels.actions }) }))] })), loading ? (skeletonRows.map((rowIndex) => (_jsxs("div", { role: "row", className: bodyRow, "data-skeleton": "", style: { opacity: 1 - rowIndex * skeletonRowFade }, children: [selectable && (_jsx("div", { role: "cell", className: cx(cell, selectCell), children: _jsx(Skeleton, { shape: "square", className: skeletonCheckbox }) })), shownColumns.map((column, columnIndex) => (_jsx("div", { role: "cell", className: cellClass(column), "data-align": column.columnDef.meta?.align, children: _jsx(SkeletonCell, { shape: column.columnDef.meta?.skeleton, width: skeletonWidths[(rowIndex + columnIndex) % skeletonWidths.length] }) }, column.id))), rowActions && _jsx("div", { role: "cell", className: cell })] }, rowIndex)))) : showEmpty ? (_jsx("div", { role: "row", className: emptyRow, children: _jsx("div", { role: "cell", "aria-colspan": columnCount, className: emptyCell, children: emptyContent }) })) : (drawBody())] }), footer, filterColumn && filterField && onFiltersChange && (_jsx(Popover, { open: true, onOpenChange: (open) => {
|
|
498
499
|
if (!open)
|
|
499
500
|
setFilterColumnId(null);
|
|
500
501
|
}, anchor: headRefs.current.get(filterColumn.id) ?? null, density: "compact", children: _jsx("div", { className: columnFilter, children: _jsx(FilterValueEditor, { field: filterField, value: filters?.find((filter) => filter.field === filterField.key), onChange: (filter) => onFiltersChange(replaceFilter(filters ?? [], filter)) }) }) }))] }));
|
|
@@ -511,6 +512,8 @@ const emptySelection = {};
|
|
|
511
512
|
const emptyVisibility = {};
|
|
512
513
|
const emptyOrder = [];
|
|
513
514
|
const skeletonRows = [0, 1, 2, 3, 4];
|
|
515
|
+
// Each loading row a little fainter than the one above, so the list reads as fading out.
|
|
516
|
+
const skeletonRowFade = 0.08;
|
|
514
517
|
const skeletonWidths = ["70%", "45%", "85%", "55%"];
|
|
515
518
|
/** What takes a click of its own inside a row, so pressing it leaves the row alone. */
|
|
516
519
|
const interactiveSelector = "a:not([data-row-link]), button, input, label, select, textarea, [role=button], [role=checkbox], [role=combobox], [role=menuitem], [contenteditable=true]";
|
|
@@ -568,7 +571,7 @@ function compareSortValues(left, right, columnId) {
|
|
|
568
571
|
// The surface a pinned cell rebuilds: the list's own surfaces are translucent, so a pinned cell
|
|
569
572
|
// redraws them on the solid canvas, or the columns scrolling under it would show through.
|
|
570
573
|
const frame = css({
|
|
571
|
-
"--row-gap-inline": "token(spacing.layout.
|
|
574
|
+
"--row-gap-inline": "token(spacing.layout.clusterGap)",
|
|
572
575
|
"--row-pad-inline": "token(spacing.panel.comfortable)",
|
|
573
576
|
"--row-pad-block": "token(spacing.panel.default)",
|
|
574
577
|
"--pinned-background": "token(colors.bg.canvas)",
|
|
@@ -583,9 +586,9 @@ const frame = css({
|
|
|
583
586
|
"&[data-variant=framed]": {
|
|
584
587
|
border: "1px solid token(colors.border.panel)",
|
|
585
588
|
borderRadius: "action",
|
|
586
|
-
background: "
|
|
589
|
+
background: "token(gradients.card)",
|
|
590
|
+
boxShadow: "card",
|
|
587
591
|
_light: {
|
|
588
|
-
background: "bg.card",
|
|
589
592
|
"--pinned-background": "token(colors.bg.card)",
|
|
590
593
|
"--pinned-layers": "none",
|
|
591
594
|
},
|
|
@@ -593,10 +596,11 @@ const frame = css({
|
|
|
593
596
|
"&[data-variant=framed][data-density=compact]": {
|
|
594
597
|
"--row-pad-block": "token(spacing.control.compactBlock)",
|
|
595
598
|
},
|
|
599
|
+
// A plain list has no frame to inset from: its cells pad themselves, half the column gap a side.
|
|
596
600
|
"&[data-variant=plain]": {
|
|
597
601
|
"--row-gap-inline": "0px",
|
|
598
602
|
"--row-pad-inline": "0px",
|
|
599
|
-
"--row-pad-block": "token(spacing.
|
|
603
|
+
"--row-pad-block": "token(spacing.panel.default)",
|
|
600
604
|
"--pinned-layers": "inset 0 0 0 999px token(colors.bg.panel)",
|
|
601
605
|
},
|
|
602
606
|
"&[data-variant=plain][data-density=compact]": {
|
|
@@ -615,6 +619,8 @@ const grid = css({
|
|
|
615
619
|
color: "fg.primary",
|
|
616
620
|
fontSize: "body",
|
|
617
621
|
letterSpacing: "compact",
|
|
622
|
+
// The kit's cells set their text at 100%; a plain list's lines may wrap, so they keep room.
|
|
623
|
+
lineHeight: "tight",
|
|
618
624
|
"[data-variant=plain] > &": { lineHeight: "compact" },
|
|
619
625
|
// On a phone a stacked list lays each row out as one block: the first cell takes the whole
|
|
620
626
|
// first line and the others wrap under it, an end-aligned one pushed to the far edge.
|
|
@@ -646,17 +652,13 @@ const rowBase = {
|
|
|
646
652
|
borderBottom: "1px solid token(colors.border.panel)",
|
|
647
653
|
"[data-variant=plain] &": { borderBottomColor: "border.subtle" },
|
|
648
654
|
};
|
|
655
|
+
// The kit's header row is 44px: its 12px labels centred, whatever the cells' block padding.
|
|
649
656
|
const headRow = css(rowBase, {
|
|
657
|
+
minHeight: "table.headRow",
|
|
650
658
|
color: "fg.primary",
|
|
651
659
|
fontSize: "code",
|
|
652
660
|
fontWeight: "medium",
|
|
653
661
|
lineHeight: "tight",
|
|
654
|
-
"[data-variant=plain] &": {
|
|
655
|
-
color: "fg.muted",
|
|
656
|
-
fontSize: "caption",
|
|
657
|
-
letterSpacing: "label",
|
|
658
|
-
textTransform: "uppercase",
|
|
659
|
-
},
|
|
660
662
|
"[data-fill] &": {
|
|
661
663
|
position: "sticky",
|
|
662
664
|
top: "0",
|
|
@@ -671,8 +673,9 @@ const bodyRow = css(rowBase, {
|
|
|
671
673
|
position: "relative",
|
|
672
674
|
outline: "none",
|
|
673
675
|
"&:last-child": { borderBottom: "0" },
|
|
676
|
+
// 56px: a 32px avatar or two-line cell inside the padding, the bottom hairline inside that.
|
|
674
677
|
"[data-variant=framed][data-density=default] &": {
|
|
675
|
-
minHeight: "calc(token(sizes.control.compact) + var(--row-pad-block) * 2
|
|
678
|
+
minHeight: "calc(token(sizes.control.compact) + var(--row-pad-block) * 2)",
|
|
676
679
|
},
|
|
677
680
|
// The row's wash is one layer over every cell, the pinned ones included, so they tint together.
|
|
678
681
|
_after: {
|
|
@@ -685,10 +688,11 @@ const bodyRow = css(rowBase, {
|
|
|
685
688
|
transitionProperty: "background",
|
|
686
689
|
transitionDuration: "fast",
|
|
687
690
|
},
|
|
691
|
+
// A ticked row shows it in its checkbox alone; the row open beside the list wears the selected
|
|
692
|
+
// glass, and keeps it under the pointer.
|
|
688
693
|
"&[data-pressable]": { cursor: "pointer" },
|
|
689
|
-
"&[data-pressable]:hover": { "--row-wash": "token(colors.bg.rowHover)" },
|
|
690
|
-
"
|
|
691
|
-
"&:is([data-selected], [data-active]):hover": { "--row-wash": "token(colors.bg.selectedHover)" },
|
|
694
|
+
"&[data-pressable]:not([data-active]):hover": { "--row-wash": "token(colors.bg.rowHover)" },
|
|
695
|
+
"&[data-active]": { "--row-wash": "token(gradients.selected)" },
|
|
692
696
|
_focusVisible: { focusRing: "inset", "--row-wash": "token(colors.bg.rowHover)" },
|
|
693
697
|
// Its anchor stands for the row and sits in a cell that may clip, so the row draws the ring.
|
|
694
698
|
"&:has(a[data-row-link]:focus-visible)": {
|
|
@@ -715,11 +719,13 @@ const emptyRow = css({ gridColumn: "1 / -1" });
|
|
|
715
719
|
const cellBase = {
|
|
716
720
|
minWidth: "0",
|
|
717
721
|
paddingBlock: "var(--row-pad-block)",
|
|
718
|
-
"[data-variant=plain] &": { paddingInline: "
|
|
722
|
+
"[data-variant=plain] &": { paddingInline: "panel.compact" },
|
|
719
723
|
"&[data-align=end]": { textAlign: "end", justifyContent: "flex-end" },
|
|
720
724
|
"&[data-align=end] > [data-shape]": { marginInlineStart: "auto" },
|
|
721
725
|
};
|
|
726
|
+
// The row's hairline sits inside its bottom padding, as the kit's 56px row draws it.
|
|
722
727
|
const cell = css(cellBase, {
|
|
728
|
+
paddingBottom: "calc(var(--row-pad-block) - token(sizes.border.hairline))",
|
|
723
729
|
fontWeight: "medium",
|
|
724
730
|
"[data-variant=plain] &": { fontWeight: "normal" },
|
|
725
731
|
"& a": { color: "inherit", textDecoration: "none" },
|
|
@@ -817,13 +823,42 @@ const headButton = css({
|
|
|
817
823
|
cursor: "pointer",
|
|
818
824
|
borderRadius: "control",
|
|
819
825
|
_focusVisible: { focusRing: "outer" },
|
|
820
|
-
|
|
826
|
+
// The sort caret shows only while the column is sorted, pointed at, focused or its menu open.
|
|
827
|
+
"& svg": { flexShrink: "0", color: "fg.muted", opacity: "0", transition: "opacity .15s" },
|
|
821
828
|
"&[data-sorted] svg": { color: "fg.primary" },
|
|
822
|
-
|
|
823
|
-
// A sort toggle shows its caret only while pointed at or sorted; a head menu's always shows.
|
|
824
|
-
"&[data-toggle] svg": { opacity: "0", transition: "opacity .15s" },
|
|
825
|
-
"&[data-toggle]:is(:hover, :focus-visible, [data-sorted]) svg": { opacity: "1" },
|
|
829
|
+
"&:is(:hover, :focus-visible, [data-sorted], [data-popup-open]) svg": { opacity: "1" },
|
|
826
830
|
"[data-align=end] > &": { marginInlineStart: "auto" },
|
|
827
831
|
});
|
|
832
|
+
// Past the skeleton's own shape sizes, which match on its `data-shape` too.
|
|
833
|
+
const skeletonCheckbox = css({
|
|
834
|
+
"&[data-shape][data-ciridae-ui]": { width: "control.checkbox", borderRadius: "control" },
|
|
835
|
+
});
|
|
836
|
+
// A loading cell in its column's shape: the kit's skeleton row draws two lines for the primary
|
|
837
|
+
// column, a 20px pill for a badge and a 24px circle beside a line for a person.
|
|
838
|
+
const skeletonLines = css({
|
|
839
|
+
display: "grid",
|
|
840
|
+
gap: "layout.controlGap",
|
|
841
|
+
width: "100%",
|
|
842
|
+
lineHeight: "tight",
|
|
843
|
+
});
|
|
844
|
+
const skeletonPill = css({
|
|
845
|
+
"&[data-shape][data-ciridae-ui]": { width: "80px", height: "control.mark", borderRadius: "pill" },
|
|
846
|
+
});
|
|
847
|
+
const skeletonPerson = css({
|
|
848
|
+
display: "flex",
|
|
849
|
+
alignItems: "center",
|
|
850
|
+
gap: "layout.controlGap",
|
|
851
|
+
width: "100%",
|
|
852
|
+
});
|
|
853
|
+
const skeletonAvatar = css({ "&[data-shape][data-ciridae-ui]": { width: "avatar.menu" } });
|
|
854
|
+
function SkeletonCell({ shape, width, }) {
|
|
855
|
+
if (shape === "lines")
|
|
856
|
+
return (_jsxs("span", { className: skeletonLines, children: [_jsx(Skeleton, { shape: "text", width: width }), _jsx(Skeleton, { shape: "text", height: "caption", width: "45%" })] }));
|
|
857
|
+
if (shape === "pill")
|
|
858
|
+
return _jsx(Skeleton, { className: skeletonPill });
|
|
859
|
+
if (shape === "person")
|
|
860
|
+
return (_jsxs("span", { className: skeletonPerson, children: [_jsx(Skeleton, { shape: "circle", className: skeletonAvatar }), _jsx(Skeleton, { shape: "text", width: width })] }));
|
|
861
|
+
return shape ?? _jsx(Skeleton, { shape: "text", width: width });
|
|
862
|
+
}
|
|
828
863
|
const columnFilter = css({ display: "flex", flexDirection: "column", width: "260px" });
|
|
829
864
|
const visuallyHidden = css({ srOnly: true });
|
|
@@ -9,7 +9,7 @@ import { useState } from "react";
|
|
|
9
9
|
import { css, cx } from "#primitives/css";
|
|
10
10
|
import { Calendar } from "./calendar.js";
|
|
11
11
|
import { useControllableState } from "./controllable-state.js";
|
|
12
|
-
import {
|
|
12
|
+
import { glassMenuDivider, glassMenuRow } from "./glass-menu.js";
|
|
13
13
|
import { icon } from "./icon.js";
|
|
14
14
|
import { useCiridaeLocale } from "./locale.js";
|
|
15
15
|
import { Popover } from "./overlays.js";
|
|
@@ -82,7 +82,7 @@ const trigger = css({
|
|
|
82
82
|
paddingInline: "control.compactInline",
|
|
83
83
|
border: "1px solid transparent",
|
|
84
84
|
borderRadius: "action",
|
|
85
|
-
background: "
|
|
85
|
+
background: "token(gradients.selected)",
|
|
86
86
|
color: "fg.primary",
|
|
87
87
|
fontFamily: "sans",
|
|
88
88
|
fontSize: "body",
|
|
@@ -90,31 +90,20 @@ const trigger = css({
|
|
|
90
90
|
letterSpacing: "compact",
|
|
91
91
|
whiteSpace: "nowrap",
|
|
92
92
|
cursor: "pointer",
|
|
93
|
-
_hover: { background: "
|
|
93
|
+
_hover: { background: "token(gradients.raisedHover)" },
|
|
94
94
|
"&[data-popup-open]": { borderColor: "fg.primary" },
|
|
95
95
|
_focusVisible: { focusRing: "outer" },
|
|
96
96
|
});
|
|
97
97
|
const options = css({ display: "grid", width: "222px" });
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
alignItems: "center",
|
|
101
|
-
gap: "layout.controlGap",
|
|
102
|
-
height: "control.compact",
|
|
103
|
-
paddingInline: "menu.itemInline",
|
|
98
|
+
// A menu row on the popover's glass sheet.
|
|
99
|
+
const option = css(glassMenuRow, {
|
|
104
100
|
border: "0",
|
|
105
|
-
borderRadius: "control",
|
|
106
101
|
background: "transparent",
|
|
107
|
-
|
|
108
|
-
font: "inherit",
|
|
109
|
-
fontSize: "body",
|
|
110
|
-
fontWeight: "medium",
|
|
111
|
-
letterSpacing: "compact",
|
|
102
|
+
fontFamily: "inherit",
|
|
112
103
|
textAlign: "start",
|
|
113
|
-
cursor: "pointer",
|
|
114
|
-
_hover: { background: "bg.glass" },
|
|
115
|
-
_focusVisible: { focusRing: "inset" },
|
|
116
104
|
});
|
|
117
|
-
const
|
|
105
|
+
const optionsDivider = css(glassMenuDivider);
|
|
106
|
+
const checkSlot = css({ display: "inline-flex", width: "mark.inline", flexShrink: "0" });
|
|
118
107
|
/**
|
|
119
108
|
* A select-shaped trigger opening the presets, and Pick dates, which swaps them for a calendar:
|
|
120
109
|
* the first day picked starts the range and the second ends it.
|
|
@@ -149,5 +138,5 @@ export function DateRangePicker({ value: ownValue, defaultValue = { kind: "prese
|
|
|
149
138
|
return (_jsx(Popover, { open: open, onOpenChange: changeOpen, density: "compact", trigger: _jsxs("button", { type: "button", className: cx(trigger, className), "aria-label": `${labels.label}: ${valueLabel}`, "data-ciridae-ui": "", "data-edge": "glass", children: [valueLabel, _jsx(CaretDownIcon, { className: icon({ size: "small" }) })] }), children: picking ? (_jsx(Calendar, { month: month, selected: start, onMonthChange: setMonth, onSelect: pickDay })) : (_jsxs("div", { className: options, children: [presets.map((preset) => (_jsxs("button", { type: "button", className: option, onClick: () => {
|
|
150
139
|
setValue({ kind: "preset", preset: preset.value });
|
|
151
140
|
changeOpen(false);
|
|
152
|
-
}, children: [_jsx("span", { className: checkSlot, children: value.kind === "preset" && value.preset === preset.value && (_jsx(CheckIcon, { className: icon({ size: "small" }), weight: "bold" })) }), preset.label] }, preset.value))), _jsx(
|
|
141
|
+
}, children: [_jsx("span", { className: checkSlot, children: value.kind === "preset" && value.preset === preset.value && (_jsx(CheckIcon, { className: icon({ size: "small" }), weight: "bold" })) }), preset.label] }, preset.value))), _jsx("div", { className: optionsDivider, role: "separator" }), _jsxs("button", { type: "button", className: option, onClick: () => setPicking(true), children: [_jsx("span", { className: checkSlot, children: value.kind === "custom" && (_jsx(CheckIcon, { className: icon({ size: "small" }), weight: "bold" })) }), labels.pickDates] })] })) }));
|
|
153
142
|
}
|
|
@@ -8,4 +8,4 @@ import { type DateInput } from "./locale.js";
|
|
|
8
8
|
export declare function DateTime({ value, mode, }: {
|
|
9
9
|
value: DateInput | null;
|
|
10
10
|
mode?: "auto" | "date" | "dateTime" | "relative";
|
|
11
|
-
}): import("
|
|
11
|
+
}): import("react").JSX.Element | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** A Wizard starts a new height scope on each step; filtering within that step keeps its height. */
|
|
2
|
-
export declare const DialogHeightResetContext: import("
|
|
2
|
+
export declare const DialogHeightResetContext: import("react").Context<(() => void) | null>;
|
|
@@ -49,7 +49,7 @@ export type DocumentViewerProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
49
49
|
actions?: ReactNode;
|
|
50
50
|
labels?: Partial<CiridaeLabels["documentViewer"]>;
|
|
51
51
|
};
|
|
52
|
-
export declare function DocumentViewer({ pages, regions, activeRegionId: ownActiveRegionId, defaultActiveRegionId, onActiveRegionChange, pageId: ownPageId, defaultPageId, onPageChange, zoom: ownZoom, defaultZoom, onZoomChange, aside, actions, labels: ownLabels, className, ...props }: DocumentViewerProps): import("
|
|
52
|
+
export declare function DocumentViewer({ pages, regions, activeRegionId: ownActiveRegionId, defaultActiveRegionId, onActiveRegionChange, pageId: ownPageId, defaultPageId, onPageChange, zoom: ownZoom, defaultZoom, onZoomChange, aside, actions, labels: ownLabels, className, ...props }: DocumentViewerProps): import("react").JSX.Element;
|
|
53
53
|
export type DocumentFieldProps = useRender.ComponentProps<"button"> & {
|
|
54
54
|
/** The region this field was read from; selecting either marks the other. */
|
|
55
55
|
regionId: string;
|
|
@@ -59,4 +59,4 @@ export type DocumentFieldProps = useRender.ComponentProps<"button"> & {
|
|
|
59
59
|
* selected, marked while its region is hovered, and scrolled into view when its region is
|
|
60
60
|
* selected on the page.
|
|
61
61
|
*/
|
|
62
|
-
export declare function DocumentField({ regionId, render, className, onClick, onMouseEnter, onMouseLeave, ...props }: DocumentFieldProps): import("
|
|
62
|
+
export declare function DocumentField({ regionId, render, className, onClick, onMouseEnter, onMouseLeave, ...props }: DocumentFieldProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -14,16 +14,21 @@ export type DrawerProps = Omit<ComponentProps<typeof BaseDrawer.Root>, "children
|
|
|
14
14
|
size?: "narrow" | "regular" | "large";
|
|
15
15
|
children: ReactNode;
|
|
16
16
|
};
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* A sheet docked at the window's right edge beside the page, which stays usable: it is not modal
|
|
19
|
+
* and a click outside leaves it open, so Escape or its close button closes it. Pass `modal` or
|
|
20
|
+
* `disablePointerDismissal` to change either.
|
|
21
|
+
*/
|
|
22
|
+
export declare function Drawer({ title, icon: titleIcon, eyebrow, subtitle, titleAccessory, actions, size, children, ...rootProps }: DrawerProps): import("react").JSX.Element;
|
|
18
23
|
export declare function DrawerBody({ flush, className, ...props }: ComponentProps<"div"> & {
|
|
19
24
|
flush?: boolean;
|
|
20
|
-
}): import("
|
|
21
|
-
export declare function DrawerForm({ className, ...props }: ComponentProps<"form">): import("
|
|
25
|
+
}): import("react").JSX.Element;
|
|
26
|
+
export declare function DrawerForm({ className, ...props }: ComponentProps<"form">): import("react").JSX.Element;
|
|
22
27
|
export type DrawerFooterProps = ComponentProps<"footer"> & {
|
|
23
28
|
/** Muted text at the footer's leading edge saying what the actions do, before the actions. */
|
|
24
29
|
note?: ReactNode;
|
|
25
30
|
};
|
|
26
|
-
export declare function DrawerFooter({ note, className, children, ...props }: DrawerFooterProps): import("
|
|
31
|
+
export declare function DrawerFooter({ note, className, children, ...props }: DrawerFooterProps): import("react").JSX.Element;
|
|
27
32
|
export type DrawerFieldProps = {
|
|
28
33
|
label: ReactNode;
|
|
29
34
|
/** Muted after the label, such as `Optional` or where a value was filled in from. */
|
|
@@ -39,6 +44,6 @@ export type DrawerFieldProps = {
|
|
|
39
44
|
* A labelled form field. Its `<label>` points at the control inside, and its helper or error
|
|
40
45
|
* describes it: `Input`, `Textarea`, `Select` and `Combobox` take the ids from the field.
|
|
41
46
|
*/
|
|
42
|
-
export declare function DrawerField({ label, hint, helper, error, controlId, children }: DrawerFieldProps): import("
|
|
47
|
+
export declare function DrawerField({ label, hint, helper, error, controlId, children }: DrawerFieldProps): import("react").JSX.Element;
|
|
43
48
|
/** Two fields side by side. */
|
|
44
|
-
export declare function DrawerFieldRow({ className, ...props }: ComponentProps<"div">): import("
|
|
49
|
+
export declare function DrawerFieldRow({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
@@ -9,55 +9,51 @@ import { HotkeyLayer } from "./hotkeys.js";
|
|
|
9
9
|
import { icon } from "./icon.js";
|
|
10
10
|
import { Eyebrow, heading } from "./layout.js";
|
|
11
11
|
import { useCiridaeLocale } from "./locale.js";
|
|
12
|
-
const backdrop = css({
|
|
13
|
-
position: "fixed",
|
|
14
|
-
inset: "none",
|
|
15
|
-
zIndex: "drawer",
|
|
16
|
-
background: "bg.backdrop",
|
|
17
|
-
transitionProperty: "opacity",
|
|
18
|
-
transitionDuration: "fast",
|
|
19
|
-
"&[data-starting-style], &[data-ending-style]": { opacity: "0" },
|
|
20
|
-
_motionReduce: { transitionDuration: "0ms" },
|
|
21
|
-
});
|
|
22
12
|
const viewport = css({ position: "fixed", inset: "none", zIndex: "drawer", pointerEvents: "none" });
|
|
13
|
+
/*
|
|
14
|
+
* A drawer sits beside the page, which stays usable: no scrim, docked to the window's right edge
|
|
15
|
+
* at full height, a glass shell holding the sheet. The shell's padding is what keeps the sheet off
|
|
16
|
+
* the window's edges, level with the main panel; a phone takes the sheet to the edges.
|
|
17
|
+
*/
|
|
23
18
|
const popup = cva({
|
|
24
19
|
base: {
|
|
25
20
|
position: "absolute",
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
insetBlock: "panel.compact",
|
|
29
|
-
insetInlineEnd: "panel.compact",
|
|
21
|
+
insetBlock: "none",
|
|
22
|
+
insetInlineEnd: "none",
|
|
30
23
|
display: "flex",
|
|
31
|
-
|
|
24
|
+
padding: "panel.compact",
|
|
32
25
|
pointerEvents: "auto",
|
|
33
26
|
outline: "none",
|
|
34
27
|
textStyle: "body",
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
border: "1px solid token(colors.border.divider)",
|
|
29
|
+
borderRadius: "shell",
|
|
30
|
+
background: "bg.drawerShell",
|
|
31
|
+
backdropFilter: "blur(token(blurs.drawerShell))",
|
|
32
|
+
boxShadow: "drawerShell",
|
|
33
|
+
_phone: { padding: "none", border: "0", borderRadius: "0" },
|
|
40
34
|
// Base UI drives live swipe drag through this custom property; the resting
|
|
41
35
|
// transform must reference it or dragging won't visually track the pointer.
|
|
42
36
|
transform: "translateX(var(--drawer-swipe-movement-x, 0px))",
|
|
43
37
|
transitionProperty: "transform",
|
|
44
38
|
transitionDuration: "default",
|
|
45
39
|
"&[data-starting-style], &[data-ending-style]": {
|
|
46
|
-
transform: "translateX(
|
|
47
|
-
_rtl: { transform: "translateX(
|
|
40
|
+
transform: "translateX(100%)",
|
|
41
|
+
_rtl: { transform: "translateX(-100%)" },
|
|
48
42
|
},
|
|
49
43
|
"&[data-swiping]": { transitionDuration: "0ms" },
|
|
50
44
|
_motionReduce: { transitionDuration: "0ms" },
|
|
51
45
|
},
|
|
46
|
+
// The sheet's width, plus the shell's padding and its 1px edge on each side.
|
|
52
47
|
variants: {
|
|
53
48
|
size: {
|
|
54
|
-
//
|
|
49
|
+
// The assistant and a preview.
|
|
55
50
|
narrow: {
|
|
56
|
-
width: "min(calc(
|
|
51
|
+
width: "min(100vw, calc(token(sizes.overlay.sheetNarrow) + token(spacing.panel.compact) * 2 + 2px))",
|
|
57
52
|
_phone: { width: "100vw" },
|
|
58
53
|
},
|
|
54
|
+
// Create, edit and act.
|
|
59
55
|
regular: {
|
|
60
|
-
width: "min(calc(
|
|
56
|
+
width: "min(100vw, calc(token(sizes.overlay.sheet) + token(spacing.panel.compact) * 2 + 2px))",
|
|
61
57
|
_phone: { width: "100vw" },
|
|
62
58
|
},
|
|
63
59
|
// Near the full viewport, for content such as logs that needs the room.
|
|
@@ -72,26 +68,51 @@ const panel = css({
|
|
|
72
68
|
minWidth: "0",
|
|
73
69
|
minHeight: "0",
|
|
74
70
|
flexDirection: "column",
|
|
71
|
+
overflow: "hidden",
|
|
72
|
+
border: "1px solid token(colors.border.divider)",
|
|
73
|
+
borderRadius: "action",
|
|
74
|
+
background: "bg.drawerSheet",
|
|
75
|
+
boxShadow: "soft",
|
|
75
76
|
color: "fg.primary",
|
|
77
|
+
_phone: { border: "0", borderRadius: "0" },
|
|
76
78
|
});
|
|
77
|
-
// At least the app header's height, so on a desktop
|
|
78
|
-
// panel's beside it: both start one shell gap from the window's top.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
79
|
+
// At least the app header's height, so on a desktop a title-only sheet's header rule lines up with
|
|
80
|
+
// the main panel's beside it: both start one shell gap from the window's top. Under a subtitle it
|
|
81
|
+
// takes the design's even 16px padding, its close button at the top. The narrow sheet's header is
|
|
82
|
+
// one line exactly the app header's height, its 34px round buttons centred in it.
|
|
83
|
+
const header = cva({
|
|
84
|
+
base: {
|
|
85
|
+
display: "flex",
|
|
86
|
+
flexDirection: "column",
|
|
87
|
+
justifyContent: "center",
|
|
88
|
+
gap: "layout.contentGap",
|
|
89
|
+
minHeight: "shell.header",
|
|
90
|
+
paddingBlock: "panel.default",
|
|
91
|
+
paddingInlineStart: "panel.comfortable",
|
|
92
|
+
paddingInlineEnd: "panel.default",
|
|
93
|
+
borderBottom: "1px solid token(colors.border.divider)",
|
|
94
|
+
"&:has([data-sheet-subtitle])": {
|
|
95
|
+
paddingBlock: "panel.comfortable",
|
|
96
|
+
"& > [data-header-line]": { alignItems: "flex-start" },
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
// The narrow header is the Ask Ciridae drawer's one line: 8px between its title and actions.
|
|
100
|
+
variants: {
|
|
101
|
+
size: {
|
|
102
|
+
narrow: { gap: "layout.controlGap", height: "shell.header", paddingBlock: "none" },
|
|
103
|
+
regular: { paddingInlineEnd: "panel.comfortable" },
|
|
104
|
+
large: { paddingInlineEnd: "panel.comfortable" },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
89
107
|
});
|
|
90
|
-
const headerLine =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
108
|
+
const headerLine = cva({
|
|
109
|
+
base: {
|
|
110
|
+
display: "flex",
|
|
111
|
+
alignItems: "center",
|
|
112
|
+
justifyContent: "space-between",
|
|
113
|
+
gap: "layout.contentGap",
|
|
114
|
+
},
|
|
115
|
+
variants: { size: { narrow: { gap: "layout.controlGap" }, regular: {}, large: {} } },
|
|
95
116
|
});
|
|
96
117
|
const titleBlock = css({
|
|
97
118
|
display: "flex",
|
|
@@ -107,12 +128,21 @@ const titleLine = css({
|
|
|
107
128
|
gap: "layout.contentGap",
|
|
108
129
|
minWidth: "0",
|
|
109
130
|
});
|
|
110
|
-
const titleStyle =
|
|
111
|
-
|
|
131
|
+
const titleStyle = css({ minWidth: "0", lineHeight: "tight" });
|
|
132
|
+
const subtitleStyle = css({
|
|
133
|
+
margin: "none",
|
|
134
|
+
color: "fg.label",
|
|
135
|
+
fontSize: "code",
|
|
136
|
+
fontWeight: "medium",
|
|
137
|
+
letterSpacing: "compact",
|
|
138
|
+
lineHeight: "tight",
|
|
139
|
+
});
|
|
140
|
+
// The sheet's mark before its title, muted like the agent sheet's sparkle. A flex row of its own,
|
|
141
|
+
// so the heading stays the title's line high rather than an inline box's.
|
|
112
142
|
const titleMark = css({
|
|
113
|
-
display: "
|
|
143
|
+
display: "flex",
|
|
114
144
|
alignItems: "center",
|
|
115
|
-
gap: "
|
|
145
|
+
gap: "layout.controlGap",
|
|
116
146
|
minWidth: "0",
|
|
117
147
|
"& > svg": { flexShrink: "0", color: "fg.muted" },
|
|
118
148
|
});
|
|
@@ -154,10 +184,9 @@ const footer = css({
|
|
|
154
184
|
alignItems: "center",
|
|
155
185
|
justifyContent: "flex-end",
|
|
156
186
|
flexWrap: "wrap",
|
|
157
|
-
gap: "layout.
|
|
187
|
+
gap: "layout.tightGap",
|
|
158
188
|
padding: "panel.comfortable",
|
|
159
|
-
borderTop: "1px solid token(colors.border.
|
|
160
|
-
background: "bg.card",
|
|
189
|
+
borderTop: "1px solid token(colors.border.divider)",
|
|
161
190
|
});
|
|
162
191
|
const footerNote = css({
|
|
163
192
|
flex: "1",
|
|
@@ -166,12 +195,20 @@ const footerNote = css({
|
|
|
166
195
|
fontWeight: "medium",
|
|
167
196
|
letterSpacing: "compact",
|
|
168
197
|
});
|
|
169
|
-
const footerActions = css({ display: "flex", alignItems: "center", gap: "layout.
|
|
198
|
+
const footerActions = css({ display: "flex", alignItems: "center", gap: "layout.tightGap" });
|
|
199
|
+
/**
|
|
200
|
+
* A sheet docked at the window's right edge beside the page, which stays usable: it is not modal
|
|
201
|
+
* and a click outside leaves it open, so Escape or its close button closes it. Pass `modal` or
|
|
202
|
+
* `disablePointerDismissal` to change either.
|
|
203
|
+
*/
|
|
170
204
|
export function Drawer({ title, icon: titleIcon, eyebrow, subtitle, titleAccessory, actions, size = "regular", children, ...rootProps }) {
|
|
171
205
|
const { labels, dir } = useCiridaeLocale();
|
|
172
|
-
|
|
206
|
+
// The narrow sheet's title is body size, as the app header's is, beside a 34px close.
|
|
207
|
+
const narrow = size === "narrow";
|
|
208
|
+
const titleClassName = cx(heading({ size: narrow ? "small" : "medium" }), titleStyle);
|
|
209
|
+
const close = (_jsx(BaseDrawer.Close, { render: _jsx(IconButton, { "aria-label": labels.common.close, size: narrow ? "medium" : "small" }), children: _jsx(XIcon, { className: icon({ size: "small" }) }) }));
|
|
173
210
|
const titleContent = titleIcon ? (_jsxs("span", { className: titleMark, children: [titleIcon, title] })) : (title);
|
|
174
|
-
return (_jsx(BaseDrawer.Root, { ...rootProps, swipeDirection: dir === "rtl" ? "left" : "right", children: _jsx(BaseDrawer.Portal, { children:
|
|
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: title }), 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] }) }) }) }) }) }));
|
|
175
212
|
}
|
|
176
213
|
export function DrawerBody({ flush = false, className, ...props }) {
|
|
177
214
|
return (_jsx(BaseDrawer.Content, { ...props, className: cx(body({ flush }), className), "data-ciridae-ui": "" }));
|
|
@@ -186,7 +223,7 @@ export function DrawerFooter({ note, className, children, ...props }) {
|
|
|
186
223
|
const field = css({
|
|
187
224
|
display: "flex",
|
|
188
225
|
flexDirection: "column",
|
|
189
|
-
gap: "
|
|
226
|
+
gap: "layout.controlGap",
|
|
190
227
|
minWidth: "0",
|
|
191
228
|
});
|
|
192
229
|
const fieldLabelRow = css({
|
|
@@ -198,7 +235,7 @@ const fieldLabelRow = css({
|
|
|
198
235
|
letterSpacing: "compact",
|
|
199
236
|
lineHeight: "tight",
|
|
200
237
|
});
|
|
201
|
-
const fieldHint = css({ color: "fg.
|
|
238
|
+
const fieldHint = css({ color: "fg.subtle" });
|
|
202
239
|
const fieldError = css({
|
|
203
240
|
margin: "none",
|
|
204
241
|
color: "accent.red",
|
|
@@ -18,16 +18,16 @@ export type DropzoneProps = useRender.ComponentProps<"div"> & {
|
|
|
18
18
|
accept?: string;
|
|
19
19
|
};
|
|
20
20
|
/** Drop or paste files onto the element; while dragged over it carries `data-dragging`. */
|
|
21
|
-
export declare function Dropzone({ onFiles, dropLabel, disabled, accept, render, className, children, ...props }: DropzoneProps): import("
|
|
21
|
+
export declare function Dropzone({ onFiles, dropLabel, disabled, accept, render, className, children, ...props }: DropzoneProps): import("react").JSX.Element;
|
|
22
22
|
/** The enclosing `Dropzone`'s picker, for a trigger of the caller's own, such as an icon button. */
|
|
23
23
|
export declare function useDropzonePicker(): DropzoneContextValue;
|
|
24
24
|
export type DropzoneTriggerProps = Omit<ButtonProps, "onClick">;
|
|
25
25
|
/** Opens the enclosing `Dropzone`'s file picker; a paperclip unless it sets its own icon. */
|
|
26
|
-
export declare function DropzoneTrigger({ icon: triggerIcon, variant, disabled, ...props }: DropzoneTriggerProps): import("
|
|
26
|
+
export declare function DropzoneTrigger({ icon: triggerIcon, variant, disabled, ...props }: DropzoneTriggerProps): import("react").JSX.Element;
|
|
27
27
|
/** A dashed pad at rest inside a `Dropzone`: drop files on it, or browse for them. */
|
|
28
28
|
export declare function DropzonePad({ className }: {
|
|
29
29
|
className?: string;
|
|
30
|
-
}): import("
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
31
|
export type DropzoneFileListProps = {
|
|
32
32
|
files: readonly File[];
|
|
33
33
|
onRemove: (file: File) => void;
|
|
@@ -42,6 +42,6 @@ export type DropzoneFileListProps = {
|
|
|
42
42
|
className?: string;
|
|
43
43
|
};
|
|
44
44
|
/** One row per file: a thumbnail for an image, else its type's icon, its name and size, remove. */
|
|
45
|
-
export declare function DropzoneFileList({ files, onRemove, pending, disabled, variant, className, }: DropzoneFileListProps): import("
|
|
45
|
+
export declare function DropzoneFileList({ files, onRemove, pending, disabled, variant, className, }: DropzoneFileListProps): import("react").JSX.Element | null;
|
|
46
46
|
/** A file's type as an icon: PDF, archive, text, or a plain file. */
|
|
47
47
|
export declare function fileTypeIcon(file: Pick<File, "name" | "type">): ReactNode;
|