torch-glare 2.4.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/apps/lib/components/ActionButton.tsx +7 -12
- package/apps/lib/components/ActionsGroup.tsx +4 -15
- package/apps/lib/components/AlertDialog.tsx +173 -191
- package/apps/lib/components/Avatar.tsx +13 -16
- package/apps/lib/components/Badge.tsx +1 -3
- package/apps/lib/components/BadgeField.tsx +76 -71
- package/apps/lib/components/Breadcrumb.tsx +49 -85
- package/apps/lib/components/Button.tsx +20 -19
- package/apps/lib/components/ButtonGroup.tsx +31 -41
- package/apps/lib/components/Calendar.tsx +51 -29
- package/apps/lib/components/Card.tsx +2 -13
- package/apps/lib/components/ChartBlockTool.ts +17 -52
- package/apps/lib/components/Checkbox.tsx +9 -16
- package/apps/lib/components/ContextMenu.tsx +97 -96
- package/apps/lib/components/CountBadge.tsx +4 -6
- package/apps/lib/components/DataTable.tsx +196 -216
- package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
- package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
- package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
- package/apps/lib/components/DataViews/InboxView.tsx +22 -68
- package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
- package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
- package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
- package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
- package/apps/lib/components/DataViews/TableView.tsx +8 -28
- package/apps/lib/components/DataViews/TreeView.tsx +12 -40
- package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
- package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
- package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
- package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
- package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
- package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
- package/apps/lib/components/DataViews/index.ts +26 -26
- package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
- package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
- package/apps/lib/components/DataViews/types.ts +104 -115
- package/apps/lib/components/DatePicker.tsx +198 -196
- package/apps/lib/components/Dialog.tsx +92 -105
- package/apps/lib/components/Divider.tsx +21 -24
- package/apps/lib/components/Drawer.tsx +79 -139
- package/apps/lib/components/DropdownMenu.tsx +131 -171
- package/apps/lib/components/FieldHint.tsx +4 -11
- package/apps/lib/components/Form.tsx +146 -155
- package/apps/lib/components/FormStepper.tsx +9 -39
- package/apps/lib/components/HeaderBar.tsx +1 -9
- package/apps/lib/components/ImageAttachment.tsx +111 -73
- package/apps/lib/components/InnerLabelField.tsx +20 -16
- package/apps/lib/components/Input.tsx +171 -172
- package/apps/lib/components/InputField.tsx +44 -45
- package/apps/lib/components/InputOTP.tsx +68 -69
- package/apps/lib/components/Label.tsx +31 -35
- package/apps/lib/components/LabelField.tsx +4 -5
- package/apps/lib/components/LabeledCheckBox.tsx +8 -12
- package/apps/lib/components/LabeledRadio.tsx +7 -5
- package/apps/lib/components/LinkButton.tsx +2 -9
- package/apps/lib/components/LoginButton.tsx +4 -9
- package/apps/lib/components/PasswordLevel.tsx +5 -5
- package/apps/lib/components/Popover.tsx +15 -33
- package/apps/lib/components/ProfileMenu.tsx +67 -72
- package/apps/lib/components/Radio.tsx +1 -5
- package/apps/lib/components/RadioCard.tsx +9 -28
- package/apps/lib/components/ScrollArea.tsx +45 -43
- package/apps/lib/components/SearchField.tsx +49 -39
- package/apps/lib/components/SearchableSelect.tsx +8 -14
- package/apps/lib/components/SearchableTable.tsx +108 -118
- package/apps/lib/components/SearchableTree.tsx +469 -0
- package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
- package/apps/lib/components/SectionBlock.tsx +4 -16
- package/apps/lib/components/Select.tsx +53 -80
- package/apps/lib/components/SimpleSelect.tsx +196 -187
- package/apps/lib/components/Skeleton.tsx +9 -12
- package/apps/lib/components/SlideDatePicker.tsx +215 -166
- package/apps/lib/components/SpinLoading.tsx +33 -49
- package/apps/lib/components/Stepper.tsx +13 -56
- package/apps/lib/components/Switch.tsx +8 -10
- package/apps/lib/components/TabFormItem.tsx +3 -12
- package/apps/lib/components/TabSwitch.tsx +7 -34
- package/apps/lib/components/Table.tsx +60 -75
- package/apps/lib/components/TableDnDWrapper.ts +15 -48
- package/apps/lib/components/TextEditor.tsx +93 -104
- package/apps/lib/components/Textarea.tsx +8 -12
- package/apps/lib/components/Timeline.tsx +21 -41
- package/apps/lib/components/Toast.tsx +83 -83
- package/apps/lib/components/Toggle.tsx +112 -114
- package/apps/lib/components/ToggleButton.tsx +1 -1
- package/apps/lib/components/Tooltip.tsx +24 -19
- package/apps/lib/components/TransparentLabel.tsx +61 -62
- package/apps/lib/components/TreeDropDown.tsx +86 -52
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
- package/apps/lib/components/TreeFolder/icons.tsx +14 -17
- package/apps/lib/components/TreeFolder/index.ts +15 -8
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
- package/apps/lib/components/TreeFolder/types.ts +32 -32
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
- package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
- package/apps/lib/hooks/useClickOutside.ts +21 -20
- package/apps/lib/hooks/useDataViewsState.ts +86 -80
- package/apps/lib/hooks/useIsMobile.ts +12 -12
- package/apps/lib/hooks/useResize.ts +54 -65
- package/apps/lib/hooks/useTagSelection.ts +201 -201
- package/apps/lib/layouts/CNLayout.tsx +181 -140
- package/apps/lib/layouts/DataViewCard.tsx +4 -18
- package/apps/lib/layouts/FieldSection.tsx +2 -6
- package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
- package/apps/lib/providers/ThemeProvider.tsx +8 -23
- package/apps/lib/registry.json +1004 -0
- package/apps/lib/tsconfig.json +9 -0
- package/apps/lib/utils/cn.ts +1 -1
- package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
- package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
- package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
- package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
- package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
- package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
- package/apps/lib/utils/dateFormat.ts +64 -54
- package/apps/lib/utils/markdownParser.ts +2 -7
- package/apps/lib/utils/resize.ts +21 -25
- package/apps/lib/utils/types.ts +13 -13
- package/dist/bin/index.js +8 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
- package/dist/src/shared/getAvailableFiles.js +6 -1
- package/dist/src/shared/getAvailableFiles.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +7 -0
- package/dist/src/shared/loadRegistry.d.ts.map +1 -0
- package/dist/src/shared/loadRegistry.js +31 -0
- package/dist/src/shared/loadRegistry.js.map +1 -0
- package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
- package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
- package/dist/src/shared/resolveInstallPlan.js +39 -0
- package/dist/src/shared/resolveInstallPlan.js.map +1 -0
- package/dist/src/types/main.d.ts +24 -0
- package/dist/src/types/main.d.ts.map +1 -1
- package/docs/README.md +10 -2
- package/docs/components/action-button.md +30 -24
- package/docs/components/actions-group.md +26 -20
- package/docs/components/alert-dialog.md +45 -45
- package/docs/components/avatar.md +6 -2
- package/docs/components/badge-field.md +6 -2
- package/docs/components/badge.md +7 -1
- package/docs/components/breadcrumb.md +15 -40
- package/docs/components/button-group.md +13 -10
- package/docs/components/button.md +58 -33
- package/docs/components/calendar.md +26 -19
- package/docs/components/card.md +19 -16
- package/docs/components/chart-block-tool.md +128 -0
- package/docs/components/checkbox.md +16 -8
- package/docs/components/cn-layout.md +7 -1
- package/docs/components/context-menu.md +18 -25
- package/docs/components/count-badge.md +7 -1
- package/docs/components/data-table.md +45 -33
- package/docs/components/data-views-config-panel.md +15 -11
- package/docs/components/data-views-layout.md +13 -16
- package/docs/components/date-picker.md +30 -23
- package/docs/components/dialog.md +43 -42
- package/docs/components/divider.md +10 -4
- package/docs/components/drawer.md +8 -33
- package/docs/components/dropdown-menu.md +25 -34
- package/docs/components/field-hint.md +37 -25
- package/docs/components/field-section.md +9 -3
- package/docs/components/form-stepper.md +6 -0
- package/docs/components/form.md +17 -20
- package/docs/components/header-bar.md +6 -0
- package/docs/components/image-attachment.md +33 -41
- package/docs/components/inbox-view.md +16 -5
- package/docs/components/inner-label-field.md +34 -24
- package/docs/components/input-field.md +18 -10
- package/docs/components/input-otp.md +14 -11
- package/docs/components/input.md +22 -16
- package/docs/components/kanban-view.md +15 -5
- package/docs/components/label-field.md +32 -22
- package/docs/components/label.md +43 -32
- package/docs/components/labeled-check-box.md +16 -8
- package/docs/components/labeled-radio.md +18 -11
- package/docs/components/link-button.md +7 -1
- package/docs/components/login-button.md +8 -2
- package/docs/components/password-level.md +37 -24
- package/docs/components/popover.md +26 -23
- package/docs/components/profile-menu.md +38 -27
- package/docs/components/radio-card.md +16 -9
- package/docs/components/radio.md +16 -8
- package/docs/components/scroll-area.md +6 -2
- package/docs/components/search-field.md +14 -6
- package/docs/components/searchable-select.md +19 -14
- package/docs/components/searchable-table.md +18 -13
- package/docs/components/searchable-tree-dialog.md +190 -0
- package/docs/components/searchable-tree.md +200 -0
- package/docs/components/section-block.md +12 -4
- package/docs/components/select.md +23 -18
- package/docs/components/simple-select.md +14 -10
- package/docs/components/skeleton.md +43 -33
- package/docs/components/slide-date-picker.md +37 -29
- package/docs/components/spin-loading.md +32 -23
- package/docs/components/stepper.md +6 -0
- package/docs/components/switch.md +14 -6
- package/docs/components/tab-form-item.md +7 -1
- package/docs/components/tab-switch.md +13 -6
- package/docs/components/table-dnd-wrapper.md +105 -0
- package/docs/components/table-view.md +15 -5
- package/docs/components/table.md +28 -28
- package/docs/components/text-editor.md +19 -13
- package/docs/components/textarea.md +15 -7
- package/docs/components/timeline.md +6 -0
- package/docs/components/toast.md +35 -26
- package/docs/components/toggle-button.md +24 -21
- package/docs/components/toggle.md +23 -15
- package/docs/components/tooltip.md +42 -30
- package/docs/components/transparent-label.md +29 -20
- package/docs/components/tree-drop-down.md +31 -23
- package/docs/components/tree-sub-layout.md +6 -2
- package/docs/components/tree-view.md +16 -5
- package/docs/explanation/architecture.md +54 -0
- package/docs/explanation/design-system.md +52 -0
- package/docs/how-to/data-views-from-backend-response.md +6 -4
- package/docs/how-to/guides.md +24 -18
- package/docs/migration/changelog.md +38 -0
- package/docs/reference/cli.md +87 -0
- package/docs/reference/components.md +11 -12
- package/docs/reference/hooks.md +8 -8
- package/docs/reference/providers.md +22 -22
- package/docs/reference/tailwind-plugins.md +2 -2
- package/docs/reference/theme.md +85 -0
- package/docs/reference/types.md +4 -4
- package/docs/reference/utilities.md +19 -26
- package/docs/tutorials/building-first-form.md +20 -13
- package/docs/tutorials/component-composition.md +34 -50
- package/docs/tutorials/getting-started.md +2 -2
- package/docs/tutorials/theming-basics.md +13 -10
- package/package.json +31 -3
- package/dist/src/commands/block.d.ts +0 -5
- package/dist/src/commands/block.d.ts.map +0 -1
- package/dist/src/commands/block.js +0 -255
- package/dist/src/commands/block.js.map +0 -1
- package/dist/src/shared/configureFonts.d.ts +0 -6
- package/dist/src/shared/configureFonts.d.ts.map +0 -1
- package/dist/src/shared/configureFonts.js +0 -106
- package/dist/src/shared/configureFonts.js.map +0 -1
- package/dist/src/shared/configureGlobalCss.d.ts +0 -6
- package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
- package/dist/src/shared/configureGlobalCss.js +0 -154
- package/dist/src/shared/configureGlobalCss.js.map +0 -1
- package/dist/src/shared/configureTailwind.d.ts +0 -7
- package/dist/src/shared/configureTailwind.d.ts.map +0 -1
- package/dist/src/shared/configureTailwind.js +0 -163
- package/dist/src/shared/configureTailwind.js.map +0 -1
- package/dist/src/shared/detectFramework.d.ts +0 -23
- package/dist/src/shared/detectFramework.d.ts.map +0 -1
- package/dist/src/shared/detectFramework.js +0 -119
- package/dist/src/shared/detectFramework.js.map +0 -1
- package/dist/src/shared/installBaseUtils.d.ts +0 -5
- package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
- package/dist/src/shared/installBaseUtils.js +0 -79
- package/dist/src/shared/installBaseUtils.js.map +0 -1
- package/dist/src/shared/resolveAliases.d.ts +0 -24
- package/dist/src/shared/resolveAliases.d.ts.map +0 -1
- package/dist/src/shared/resolveAliases.js +0 -98
- package/dist/src/shared/resolveAliases.js.map +0 -1
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
useEffect,
|
|
5
|
-
useMemo,
|
|
6
|
-
useState,
|
|
7
|
-
type ElementType,
|
|
8
|
-
type ReactNode,
|
|
9
|
-
} from "react";
|
|
3
|
+
import { useEffect, useMemo, useState, type ElementType, type ReactNode } from "react";
|
|
10
4
|
import { Badge } from "../Badge";
|
|
11
5
|
import { FilterPanel } from "./FilterPanel";
|
|
12
6
|
import {
|
|
@@ -37,16 +31,9 @@ import { Avatar, AvatarFallback } from "../Avatar";
|
|
|
37
31
|
import { Card } from "../Card";
|
|
38
32
|
import { Divider } from "../Divider";
|
|
39
33
|
import { renderDetailView } from "../../utils/dataViews/nestedDataUtils";
|
|
40
|
-
import {
|
|
41
|
-
getByPath,
|
|
42
|
-
setByPath,
|
|
43
|
-
matchesFilterValues,
|
|
44
|
-
} from "../../utils/dataViews/pathUtils";
|
|
34
|
+
import { getByPath, setByPath, matchesFilterValues } from "../../utils/dataViews/pathUtils";
|
|
45
35
|
import { renderField } from "./fieldRenderers";
|
|
46
|
-
import {
|
|
47
|
-
resolveInboxConfig,
|
|
48
|
-
visibleFields,
|
|
49
|
-
} from "../../utils/dataViews/fieldUtils";
|
|
36
|
+
import { resolveInboxConfig, visibleFields } from "../../utils/dataViews/fieldUtils";
|
|
50
37
|
import { useIsMobile } from "../../hooks/useIsMobile";
|
|
51
38
|
import { resolveBadgeVariant } from "./badgeAdapter";
|
|
52
39
|
import { InboxViewCard } from "./InboxViewCard";
|
|
@@ -62,24 +49,20 @@ export type InboxViewProps = {
|
|
|
62
49
|
filterState?: FilterState;
|
|
63
50
|
onFilterChange?: (filters: FilterState) => void;
|
|
64
51
|
showFilters?: boolean;
|
|
65
|
-
itemHref?: (item: DynamicRecord, id:
|
|
52
|
+
itemHref?: (item: DynamicRecord, id: unknown) => string;
|
|
66
53
|
/**
|
|
67
54
|
* Component used to render each item's link when `itemHref` is set. Defaults
|
|
68
55
|
* to a plain `<a>` (full-page navigation). Pass your router's link
|
|
69
56
|
* (e.g. Next.js `Link`, React Router `Link`) for client-side navigation.
|
|
70
57
|
*/
|
|
71
58
|
linkComponent?: ElementType;
|
|
72
|
-
selectedItemId?:
|
|
59
|
+
selectedItemId?: unknown;
|
|
73
60
|
renderDetail?: (item: DynamicRecord | null) => ReactNode;
|
|
74
61
|
};
|
|
75
62
|
|
|
76
63
|
type InboxFilter = "all" | "starred" | "priority";
|
|
77
64
|
|
|
78
|
-
function getId(
|
|
79
|
-
item: DynamicRecord,
|
|
80
|
-
fallbackPath: string | undefined,
|
|
81
|
-
idx: number,
|
|
82
|
-
): any {
|
|
65
|
+
function getId(item: DynamicRecord, fallbackPath: string | undefined, idx: number): unknown {
|
|
83
66
|
if (item?.id != null) return item.id;
|
|
84
67
|
if (fallbackPath) {
|
|
85
68
|
const v = getByPath(item, fallbackPath);
|
|
@@ -88,7 +71,7 @@ function getId(
|
|
|
88
71
|
return idx;
|
|
89
72
|
}
|
|
90
73
|
|
|
91
|
-
function getInitials(name:
|
|
74
|
+
function getInitials(name: unknown): string {
|
|
92
75
|
const s = String(name ?? "?").trim();
|
|
93
76
|
if (!s) return "?";
|
|
94
77
|
return (
|
|
@@ -117,9 +100,7 @@ export function InboxView({
|
|
|
117
100
|
renderDetail,
|
|
118
101
|
}: InboxViewProps) {
|
|
119
102
|
const isMobile = useIsMobile();
|
|
120
|
-
const [selectedItem, setSelectedItem] = useState<DynamicRecord | null>(
|
|
121
|
-
data[0] || null,
|
|
122
|
-
);
|
|
103
|
+
const [selectedItem, setSelectedItem] = useState<DynamicRecord | null>(data[0] || null);
|
|
123
104
|
const [inboxFilter, setInboxFilter] = useState<InboxFilter>("all");
|
|
124
105
|
const [internalFilters, setInternalFilters] = useState<FilterState>({});
|
|
125
106
|
|
|
@@ -186,7 +167,7 @@ export function InboxView({
|
|
|
186
167
|
return String(v).toLowerCase() === "high";
|
|
187
168
|
};
|
|
188
169
|
|
|
189
|
-
const toggleStar = (itemId:
|
|
170
|
+
const toggleStar = (itemId: unknown) => {
|
|
190
171
|
if (!inboxCfg.starredField) return;
|
|
191
172
|
const updatedData = data.map((item, idx) => {
|
|
192
173
|
const cur = getId(item, idPath, idx);
|
|
@@ -201,11 +182,7 @@ export function InboxView({
|
|
|
201
182
|
if (selectedItem && getId(selectedItem, idPath, -1) === itemId) {
|
|
202
183
|
setSelectedItem((prev) =>
|
|
203
184
|
prev && inboxCfg.starredField
|
|
204
|
-
? setByPath(
|
|
205
|
-
prev,
|
|
206
|
-
inboxCfg.starredField,
|
|
207
|
-
!getByPath(prev, inboxCfg.starredField),
|
|
208
|
-
)
|
|
185
|
+
? setByPath(prev, inboxCfg.starredField, !getByPath(prev, inboxCfg.starredField))
|
|
209
186
|
: prev,
|
|
210
187
|
);
|
|
211
188
|
}
|
|
@@ -233,8 +210,8 @@ export function InboxView({
|
|
|
233
210
|
(inboxFilter === "starred" && isStarred(item)) ||
|
|
234
211
|
(inboxFilter === "priority" && isHighPriority(item));
|
|
235
212
|
|
|
236
|
-
const matchesFilters = Object.entries(activeFilters).every(
|
|
237
|
-
|
|
213
|
+
const matchesFilters = Object.entries(activeFilters).every(([path, filterValues]) =>
|
|
214
|
+
matchesFilterValues(item, path, filterValues),
|
|
238
215
|
);
|
|
239
216
|
|
|
240
217
|
return matchesInboxFilter && matchesFilters;
|
|
@@ -242,12 +219,8 @@ export function InboxView({
|
|
|
242
219
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
243
220
|
}, [data, inboxFilter, activeFilters, inboxCfg]);
|
|
244
221
|
|
|
245
|
-
const starredCount = inboxCfg.starredField
|
|
246
|
-
|
|
247
|
-
: 0;
|
|
248
|
-
const priorityCount = inboxCfg.priorityField
|
|
249
|
-
? data.filter((i) => isHighPriority(i)).length
|
|
250
|
-
: 0;
|
|
222
|
+
const starredCount = inboxCfg.starredField ? data.filter((i) => isStarred(i)).length : 0;
|
|
223
|
+
const priorityCount = inboxCfg.priorityField ? data.filter((i) => isHighPriority(i)).length : 0;
|
|
251
224
|
|
|
252
225
|
const filtersEnabled = showFilters && config.showFilters !== false;
|
|
253
226
|
const countBadge = resolveBadgeVariant("gray");
|
|
@@ -272,12 +245,7 @@ export function InboxView({
|
|
|
272
245
|
>
|
|
273
246
|
<InboxIcon className="h-4 w-4" />
|
|
274
247
|
All Items
|
|
275
|
-
<Badge
|
|
276
|
-
{...countBadge}
|
|
277
|
-
label={String(data.length)}
|
|
278
|
-
className="ml-auto"
|
|
279
|
-
size="XS"
|
|
280
|
-
/>
|
|
248
|
+
<Badge {...countBadge} label={String(data.length)} className="ml-auto" size="XS" />
|
|
281
249
|
</TabFormItem>
|
|
282
250
|
{inboxCfg.starredField && (
|
|
283
251
|
<TabFormItem
|
|
@@ -350,14 +318,12 @@ export function InboxView({
|
|
|
350
318
|
{filteredData.map((item, idx) => {
|
|
351
319
|
const itemId = getId(item, idPath, idx);
|
|
352
320
|
const selected =
|
|
353
|
-
(selectedItemId != null &&
|
|
354
|
-
|
|
355
|
-
(selectedItem != null &&
|
|
356
|
-
getId(selectedItem, idPath, -1) === itemId);
|
|
321
|
+
(selectedItemId != null && String(selectedItemId) === String(itemId)) ||
|
|
322
|
+
(selectedItem != null && getId(selectedItem, idPath, -1) === itemId);
|
|
357
323
|
|
|
358
324
|
return (
|
|
359
325
|
<InboxViewCard
|
|
360
|
-
key={itemId}
|
|
326
|
+
key={itemId as string | number}
|
|
361
327
|
item={item}
|
|
362
328
|
rowFields={displayFields}
|
|
363
329
|
selected={selected}
|
|
@@ -396,22 +362,14 @@ export function InboxView({
|
|
|
396
362
|
<div className="flex items-start gap-4 mb-6">
|
|
397
363
|
<Avatar className="h-12 w-12">
|
|
398
364
|
<AvatarFallback className="bg-background-presentation-action-primary text-content-presentation-action-primary">
|
|
399
|
-
{getInitials(
|
|
400
|
-
previewField
|
|
401
|
-
? getByPath(selectedItem, previewField.path)
|
|
402
|
-
: "",
|
|
403
|
-
)}
|
|
365
|
+
{getInitials(previewField ? getByPath(selectedItem, previewField.path) : "")}
|
|
404
366
|
</AvatarFallback>
|
|
405
367
|
</Avatar>
|
|
406
368
|
<div className="flex-1">
|
|
407
369
|
<div className="flex items-start justify-between gap-4 mb-2">
|
|
408
370
|
<div>
|
|
409
371
|
<h2 className="text-xl font-semibold text-content-presentation-global-primary mb-1">
|
|
410
|
-
{String(
|
|
411
|
-
titleField
|
|
412
|
-
? getByPath(selectedItem, titleField.path)
|
|
413
|
-
: "",
|
|
414
|
-
)}
|
|
372
|
+
{String(titleField ? getByPath(selectedItem, titleField.path) : "")}
|
|
415
373
|
</h2>
|
|
416
374
|
{previewField && (
|
|
417
375
|
<p className="text-sm text-content-presentation-global-tertiary">
|
|
@@ -424,9 +382,7 @@ export function InboxView({
|
|
|
424
382
|
</div>
|
|
425
383
|
{inboxCfg.starredField && (
|
|
426
384
|
<button
|
|
427
|
-
onClick={() =>
|
|
428
|
-
toggleStar(getId(selectedItem, idPath, -1))
|
|
429
|
-
}
|
|
385
|
+
onClick={() => toggleStar(getId(selectedItem, idPath, -1))}
|
|
430
386
|
className="hover:text-content-presentation-badge-yellow transition-colors"
|
|
431
387
|
aria-label="Toggle star"
|
|
432
388
|
>
|
|
@@ -446,9 +402,7 @@ export function InboxView({
|
|
|
446
402
|
const value = getByPath(selectedItem, field.path);
|
|
447
403
|
if (value == null) return null;
|
|
448
404
|
return (
|
|
449
|
-
<span key={field.path}>
|
|
450
|
-
{renderField(value, field, selectedItem)}
|
|
451
|
-
</span>
|
|
405
|
+
<span key={field.path}>{renderField(value, field, selectedItem)}</span>
|
|
452
406
|
);
|
|
453
407
|
})}
|
|
454
408
|
</div>
|
|
@@ -40,97 +40,88 @@ function pickRowFields(props: InboxViewCardProps): FieldConfig[] {
|
|
|
40
40
|
return collected;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function pickDateField(
|
|
44
|
-
rowFields: FieldConfig[],
|
|
45
|
-
explicit?: FieldConfig,
|
|
46
|
-
): FieldConfig | undefined {
|
|
43
|
+
function pickDateField(rowFields: FieldConfig[], explicit?: FieldConfig): FieldConfig | undefined {
|
|
47
44
|
if (explicit) return explicit;
|
|
48
45
|
return rowFields.find((f) => f.type === "date");
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
export const InboxViewCard = forwardRef<HTMLDivElement, InboxViewCardProps>(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
: allRowFields;
|
|
60
|
-
const dateLabel = props.dateLabel ?? "Created at:";
|
|
48
|
+
export const InboxViewCard = forwardRef<HTMLDivElement, InboxViewCardProps>((props, ref) => {
|
|
49
|
+
const { item, selected = false, onSelect, href, linkComponent, className } = props;
|
|
50
|
+
const allRowFields = pickRowFields(props);
|
|
51
|
+
const dateField = pickDateField(allRowFields, props.dateField);
|
|
52
|
+
const rowFields = dateField
|
|
53
|
+
? allRowFields.filter((f) => f.path !== dateField.path)
|
|
54
|
+
: allRowFields;
|
|
55
|
+
const dateLabel = props.dateLabel ?? "Created at:";
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const content: ReactNode = (
|
|
74
|
-
<>
|
|
75
|
-
<div className="flex flex-col gap-1 w-full">
|
|
76
|
-
{rowFields.map((field, idx) => {
|
|
77
|
-
const value = getByPath(item, field.path);
|
|
78
|
-
return (
|
|
79
|
-
<div key={field.path ?? idx} className="flex flex-col">
|
|
80
|
-
<div className="flex items-center gap-2">
|
|
81
|
-
<span className="w-[100px] shrink-0 typography-body-large-semibold text-content-presentation-global-secondary">
|
|
82
|
-
{field.label ?? field.path}:
|
|
83
|
-
</span>
|
|
84
|
-
<span className="h-full py-0.5 flex items-center">
|
|
85
|
-
<span className="block h-full w-px bg-black-alpha-15" />
|
|
86
|
-
</span>
|
|
87
|
-
<span className="flex-1 min-w-0 truncate typography-body-large-medium text-content-presentation-global-primary">
|
|
88
|
-
{renderField(value, field, item)}
|
|
89
|
-
</span>
|
|
90
|
-
</div>
|
|
91
|
-
{idx < rowFields.length - 1 && <Divider className="mt-1" />}
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
})}
|
|
95
|
-
</div>
|
|
57
|
+
const cardClass = cn(
|
|
58
|
+
"flex flex-col gap-2 p-3 cursor-pointer transition-colors",
|
|
59
|
+
"bg-background-presentation-form-base",
|
|
60
|
+
"border-y-2 border-transparent",
|
|
61
|
+
!selected &&
|
|
62
|
+
"hover:bg-[image:linear-gradient(0deg,rgba(151,72,255,0.05)_0%,rgba(151,72,255,0.05)_100%)] hover:border-y-[#AE71FF]",
|
|
63
|
+
selected &&
|
|
64
|
+
"bg-[image:linear-gradient(0deg,rgba(0,117,255,0.05)_0%,rgba(0,117,255,0.05)_100%)] border-y-border-presentation-state-focus",
|
|
65
|
+
className,
|
|
66
|
+
);
|
|
96
67
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
68
|
+
const content: ReactNode = (
|
|
69
|
+
<>
|
|
70
|
+
<div className="flex flex-col gap-1 w-full">
|
|
71
|
+
{rowFields.map((field, idx) => {
|
|
72
|
+
const value = getByPath(item, field.path);
|
|
73
|
+
return (
|
|
74
|
+
<div key={field.path ?? idx} className="flex flex-col">
|
|
75
|
+
<div className="flex items-center gap-2">
|
|
76
|
+
<span className="w-[100px] shrink-0 typography-body-large-semibold text-content-presentation-global-secondary">
|
|
77
|
+
{field.label ?? field.path}:
|
|
103
78
|
</span>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
79
|
+
<span className="h-full py-0.5 flex items-center">
|
|
80
|
+
<span className="block h-full w-px bg-black-alpha-15" />
|
|
81
|
+
</span>
|
|
82
|
+
<span className="flex-1 min-w-0 truncate typography-body-large-medium text-content-presentation-global-primary">
|
|
83
|
+
{renderField(value, field, item)}
|
|
108
84
|
</span>
|
|
109
85
|
</div>
|
|
86
|
+
{idx < rowFields.length - 1 && <Divider className="mt-1" />}
|
|
110
87
|
</div>
|
|
111
|
-
|
|
112
|
-
)}
|
|
113
|
-
|
|
114
|
-
);
|
|
88
|
+
);
|
|
89
|
+
})}
|
|
90
|
+
</div>
|
|
115
91
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
92
|
+
{dateField && (
|
|
93
|
+
<div className="flex items-center justify-end">
|
|
94
|
+
<div className="inline-flex items-center gap-0.5 p-0.5 rounded-md bg-black-alpha-10">
|
|
95
|
+
<div className="px-1 rounded-sm">
|
|
96
|
+
<span className="typography-labels-medium-semibold text-content-presentation-global-primary">
|
|
97
|
+
{dateLabel}
|
|
98
|
+
</span>
|
|
99
|
+
</div>
|
|
100
|
+
<div className="px-1 rounded-sm bg-black-alpha-075">
|
|
101
|
+
<span className="typography-labels-medium-semibold text-content-presentation-global-primary">
|
|
102
|
+
{renderField(getByPath(item, dateField.path), dateField, item)}
|
|
103
|
+
</span>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
</>
|
|
109
|
+
);
|
|
127
110
|
|
|
111
|
+
if (href) {
|
|
112
|
+
const LinkTag = (linkComponent ?? "a") as ElementType;
|
|
128
113
|
return (
|
|
129
|
-
<
|
|
114
|
+
<LinkTag href={href} className={cn(cardClass, "no-underline text-inherit")}>
|
|
130
115
|
{content}
|
|
131
|
-
</
|
|
116
|
+
</LinkTag>
|
|
132
117
|
);
|
|
133
|
-
}
|
|
134
|
-
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div ref={ref} onClick={onSelect} className={cardClass}>
|
|
122
|
+
{content}
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
});
|
|
135
126
|
|
|
136
127
|
InboxViewCard.displayName = "InboxViewCard";
|
|
@@ -70,11 +70,7 @@ type KanbanColumn = {
|
|
|
70
70
|
items: DynamicRecord[];
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
function getId(
|
|
74
|
-
item: DynamicRecord,
|
|
75
|
-
fallbackPath: string | undefined,
|
|
76
|
-
idx: number,
|
|
77
|
-
): any {
|
|
73
|
+
function getId(item: DynamicRecord, fallbackPath: string | undefined, idx: number): unknown {
|
|
78
74
|
if (item?.id != null) return item.id;
|
|
79
75
|
if (fallbackPath) {
|
|
80
76
|
const v = getByPath(item, fallbackPath);
|
|
@@ -117,9 +113,7 @@ export function KanbanView({
|
|
|
117
113
|
// palette rotation.
|
|
118
114
|
const resolve = (key: string, paletteIdx: number) => ({
|
|
119
115
|
title: overrides?.[key]?.label ?? key,
|
|
120
|
-
color:
|
|
121
|
-
overrides?.[key]?.color ??
|
|
122
|
-
COLUMN_PALETTE[paletteIdx % COLUMN_PALETTE.length],
|
|
116
|
+
color: overrides?.[key]?.color ?? COLUMN_PALETTE[paletteIdx % COLUMN_PALETTE.length],
|
|
123
117
|
});
|
|
124
118
|
|
|
125
119
|
if (groupField?.variants) {
|
|
@@ -200,12 +194,9 @@ export function KanbanView({
|
|
|
200
194
|
|
|
201
195
|
const renderCard = (item: DynamicRecord, idx: number) => {
|
|
202
196
|
const itemId = getId(item, idPath, idx);
|
|
203
|
-
const isDraggingThis =
|
|
204
|
-
draggedItem != null && getId(draggedItem.item, idPath, -1) === itemId;
|
|
197
|
+
const isDraggingThis = draggedItem != null && getId(draggedItem.item, idPath, -1) === itemId;
|
|
205
198
|
const titleFieldResolved = resolvedTitleField;
|
|
206
|
-
const titleValue = titleFieldResolved
|
|
207
|
-
? getByPath(item, titleFieldResolved.path)
|
|
208
|
-
: "";
|
|
199
|
+
const titleValue = titleFieldResolved ? getByPath(item, titleFieldResolved.path) : "";
|
|
209
200
|
const bodyFields = displayFields.filter(
|
|
210
201
|
(f) => f.path !== groupByField && f.path !== titleFieldResolved?.path,
|
|
211
202
|
);
|
|
@@ -240,15 +231,11 @@ export function KanbanView({
|
|
|
240
231
|
|
|
241
232
|
return (
|
|
242
233
|
<DataViewCard
|
|
243
|
-
key={itemId}
|
|
234
|
+
key={itemId as string | number}
|
|
244
235
|
draggable={!isMobile}
|
|
245
236
|
onDragStart={
|
|
246
237
|
!isMobile
|
|
247
|
-
? () =>
|
|
248
|
-
handleDragStart(
|
|
249
|
-
item,
|
|
250
|
-
String(getByPath(item, groupByField) ?? "Uncategorized"),
|
|
251
|
-
)
|
|
238
|
+
? () => handleDragStart(item, String(getByPath(item, groupByField) ?? "Uncategorized"))
|
|
252
239
|
: undefined
|
|
253
240
|
}
|
|
254
241
|
onDragEnd={!isMobile ? handleDragEnd : undefined}
|
|
@@ -258,10 +245,7 @@ export function KanbanView({
|
|
|
258
245
|
: "cursor-grab active:cursor-grabbing hover:shadow-md transition-shadow",
|
|
259
246
|
!isMobile && isDraggingThis && "opacity-40",
|
|
260
247
|
)}
|
|
261
|
-
title={
|
|
262
|
-
titleFieldResolved &&
|
|
263
|
-
renderField(titleValue, titleFieldResolved, item)
|
|
264
|
-
}
|
|
248
|
+
title={titleFieldResolved && renderField(titleValue, titleFieldResolved, item)}
|
|
265
249
|
rows={rows}
|
|
266
250
|
/>
|
|
267
251
|
);
|
|
@@ -288,8 +272,7 @@ export function KanbanView({
|
|
|
288
272
|
<div className="h-full overflow-x-auto p-2 bg-background-presentation-body-primary">
|
|
289
273
|
<div className="flex h-full gap-4" style={{ minWidth: "max-content" }}>
|
|
290
274
|
{kanbanColumns.map((column, i) => {
|
|
291
|
-
const isDropTarget =
|
|
292
|
-
draggedItem != null && dragOverColumnId === column.id;
|
|
275
|
+
const isDropTarget = draggedItem != null && dragOverColumnId === column.id;
|
|
293
276
|
return (
|
|
294
277
|
<Fragment key={column.id}>
|
|
295
278
|
<div
|
|
@@ -25,8 +25,7 @@ export function RadioRow({ value, label }: { value: string; label: string }) {
|
|
|
25
25
|
|
|
26
26
|
// Shared <Switch> with the bright-green checked track (#0AC713) from the Figma
|
|
27
27
|
// Switcher-1.0 "On" state, applied regardless of the panel's dark theme scope.
|
|
28
|
-
const SWITCH_GREEN =
|
|
29
|
-
"data-[state=checked]:bg-[#0AC713] data-[state=checked]:border-[#0AC713]";
|
|
28
|
+
const SWITCH_GREEN = "data-[state=checked]:bg-[#0AC713] data-[state=checked]:border-[#0AC713]";
|
|
30
29
|
|
|
31
30
|
type DataViewsSwitchProps = {
|
|
32
31
|
checked: boolean;
|
|
@@ -35,15 +34,6 @@ type DataViewsSwitchProps = {
|
|
|
35
34
|
|
|
36
35
|
/** Column show/hide toggle: the library <Switch> pre-styled to the panel's
|
|
37
36
|
* Figma green-checked spec. */
|
|
38
|
-
export function DataViewsSwitch({
|
|
39
|
-
checked
|
|
40
|
-
onCheckedChange,
|
|
41
|
-
}: DataViewsSwitchProps) {
|
|
42
|
-
return (
|
|
43
|
-
<Switch
|
|
44
|
-
checked={checked}
|
|
45
|
-
onCheckedChange={onCheckedChange}
|
|
46
|
-
className={SWITCH_GREEN}
|
|
47
|
-
/>
|
|
48
|
-
);
|
|
37
|
+
export function DataViewsSwitch({ checked, onCheckedChange }: DataViewsSwitchProps) {
|
|
38
|
+
return <Switch checked={checked} onCheckedChange={onCheckedChange} className={SWITCH_GREEN} />;
|
|
49
39
|
}
|