@accelint/design-toolkit 9.13.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/catalog-info.yaml +1 -1
- package/dist/components/accordion/context.d.ts +2 -2
- package/dist/components/accordion/group.d.ts +2 -2
- package/dist/components/accordion/header.d.ts +2 -2
- package/dist/components/accordion/index.d.ts +2 -2
- package/dist/components/accordion/panel.d.ts +2 -2
- package/dist/components/accordion/trigger.d.ts +2 -2
- package/dist/components/action-bar/index.d.ts +2 -2
- package/dist/components/audio/index.d.ts +2 -2
- package/dist/components/avatar/context.d.ts +4 -4
- package/dist/components/avatar/index.d.ts +2 -2
- package/dist/components/badge/context.d.ts +4 -4
- package/dist/components/badge/index.d.ts +2 -2
- package/dist/components/breadcrumbs/index.d.ts +2 -2
- package/dist/components/breadcrumbs/item.d.ts +2 -2
- package/dist/components/button/context.d.ts +8 -8
- package/dist/components/button/index.d.ts +2 -2
- package/dist/components/button/link.d.ts +2 -2
- package/dist/components/button/toggle.d.ts +2 -2
- package/dist/components/carousel/context.d.ts +4 -4
- package/dist/components/carousel/gallery.d.ts +2 -2
- package/dist/components/carousel/index.d.ts +2 -2
- package/dist/components/carousel/navigation.d.ts +3 -3
- package/dist/components/carousel/position.d.ts +2 -2
- package/dist/components/carousel/select.d.ts +2 -2
- package/dist/components/carousel/viewer.d.ts +2 -2
- package/dist/components/checkbox/context.d.ts +3 -3
- package/dist/components/checkbox/group.d.ts +2 -2
- package/dist/components/checkbox/index.d.ts +2 -2
- package/dist/components/chip/context.d.ts +4 -4
- package/dist/components/chip/deletable.d.ts +2 -2
- package/dist/components/chip/index.d.ts +2 -2
- package/dist/components/chip/list.d.ts +4 -4
- package/dist/components/chip/selectable.d.ts +2 -2
- package/dist/components/classification-badge/context.d.ts +4 -4
- package/dist/components/classification-badge/index.d.ts +2 -2
- package/dist/components/classification-banner/context.d.ts +4 -4
- package/dist/components/classification-banner/index.d.ts +2 -2
- package/dist/components/clock/index.d.ts +2 -2
- package/dist/components/color-picker/index.d.ts +2 -2
- package/dist/components/combobox-field/context.d.ts +4 -4
- package/dist/components/combobox-field/index.d.ts +2 -2
- package/dist/components/coordinate-field/context.d.ts +6 -6
- package/dist/components/coordinate-field/index.d.ts +2 -2
- package/dist/components/coordinate-field/segment.d.ts +2 -2
- package/dist/components/date-field/index.d.ts +2 -2
- package/dist/components/deferred-collection/index.d.ts +2 -2
- package/dist/components/details-list/context.d.ts +4 -4
- package/dist/components/details-list/index.d.ts +2 -2
- package/dist/components/details-list/label.d.ts +2 -2
- package/dist/components/details-list/value.d.ts +2 -2
- package/dist/components/dialog/content.d.ts +2 -2
- package/dist/components/dialog/context.d.ts +2 -2
- package/dist/components/dialog/footer.d.ts +2 -2
- package/dist/components/dialog/index.d.ts +2 -2
- package/dist/components/dialog/title.d.ts +2 -2
- package/dist/components/divider/context.d.ts +4 -4
- package/dist/components/divider/index.d.ts +2 -2
- package/dist/components/drawer/back.d.ts +2 -2
- package/dist/components/drawer/close.d.ts +2 -2
- package/dist/components/drawer/content.d.ts +2 -2
- package/dist/components/drawer/context.d.ts +2 -2
- package/dist/components/drawer/footer.d.ts +2 -2
- package/dist/components/drawer/header-title.d.ts +2 -2
- package/dist/components/drawer/index.d.ts +2 -2
- package/dist/components/drawer/layout-main.d.ts +2 -2
- package/dist/components/drawer/layout.d.ts +2 -2
- package/dist/components/drawer/menu-item.d.ts +2 -2
- package/dist/components/drawer/menu.d.ts +2 -2
- package/dist/components/drawer/panel.d.ts +2 -2
- package/dist/components/drawer/trigger.d.ts +2 -2
- package/dist/components/drawer/view.d.ts +2 -2
- package/dist/components/flashcard/index.d.ts +9 -9
- package/dist/components/floating-card/constants.d.ts +26 -0
- package/dist/components/floating-card/constants.js +40 -0
- package/dist/components/floating-card/constants.js.map +1 -0
- package/dist/components/floating-card/context.d.ts +38 -6
- package/dist/components/floating-card/context.js +24 -3
- package/dist/components/floating-card/context.js.map +1 -1
- package/dist/components/floating-card/hooks/use-card-layout.d.ts +36 -0
- package/dist/components/floating-card/hooks/use-card-layout.js +106 -0
- package/dist/components/floating-card/hooks/use-card-layout.js.map +1 -0
- package/dist/components/floating-card/hooks/use-drag.d.ts +62 -0
- package/dist/components/floating-card/hooks/use-drag.js +100 -0
- package/dist/components/floating-card/hooks/use-drag.js.map +1 -0
- package/dist/components/floating-card/hooks/use-mouse-interaction.d.ts +58 -0
- package/dist/components/floating-card/hooks/use-mouse-interaction.js +91 -0
- package/dist/components/floating-card/hooks/use-mouse-interaction.js.map +1 -0
- package/dist/components/floating-card/hooks/use-resize.d.ts +56 -0
- package/dist/components/floating-card/hooks/use-resize.js +98 -0
- package/dist/components/floating-card/hooks/use-resize.js.map +1 -0
- package/dist/components/floating-card/index.d.ts +6 -2
- package/dist/components/floating-card/index.js +24 -32
- package/dist/components/floating-card/index.js.map +1 -1
- package/dist/components/floating-card/panel.d.ts +69 -0
- package/dist/components/floating-card/panel.js +111 -0
- package/dist/components/floating-card/panel.js.map +1 -0
- package/dist/components/floating-card/provider.d.ts +10 -6
- package/dist/components/floating-card/provider.js +159 -153
- package/dist/components/floating-card/provider.js.map +1 -1
- package/dist/components/floating-card/styles.module.css +93 -39
- package/dist/components/floating-card/types.d.ts +51 -10
- package/dist/components/floating-card/utils.d.ts +8 -85
- package/dist/components/floating-card/utils.js +12 -38
- package/dist/components/floating-card/utils.js.map +1 -1
- package/dist/components/gantt/components/base-elements/point.d.ts +2 -2
- package/dist/components/gantt/components/base-elements/range.d.ts +2 -2
- package/dist/components/gantt/components/containers/external/gantt-content-container/index.d.ts +2 -2
- package/dist/components/gantt/components/containers/external/gantt-panel-container/index.d.ts +2 -2
- package/dist/components/gantt/components/containers/internal/index.d.ts +2 -2
- package/dist/components/gantt/components/containers/internal/layout-container/index.d.ts +2 -2
- package/dist/components/gantt/components/containers/internal/virtualized-content-height-container/index.d.ts +2 -2
- package/dist/components/gantt/components/content-row/block.d.ts +2 -2
- package/dist/components/gantt/components/content-row/bracket.d.ts +3 -3
- package/dist/components/gantt/components/content-row/icon-marker.d.ts +2 -2
- package/dist/components/gantt/components/content-row/index.d.ts +2 -2
- package/dist/components/gantt/components/content-row/marker.d.ts +2 -2
- package/dist/components/gantt/components/content-row/spacer.d.ts +2 -2
- package/dist/components/gantt/components/current-time/index.d.ts +2 -2
- package/dist/components/gantt/components/header/index.d.ts +3 -3
- package/dist/components/gantt/components/panel-row/index.d.ts +2 -2
- package/dist/components/gantt/components/rows-virtualizer/index.d.ts +3 -3
- package/dist/components/gantt/components/timeline/index.d.ts +2 -2
- package/dist/components/gantt/components/timeline-chunk/index.d.ts +3 -3
- package/dist/components/gantt/context/index.d.ts +4 -4
- package/dist/components/gantt/context/store/index.d.ts +4 -4
- package/dist/components/gantt/context/temporal-data/index.d.ts +4 -4
- package/dist/components/gantt/hooks/use-layout-subscription/index.js +8 -8
- package/dist/components/gantt/hooks/use-layout-subscription/index.js.map +1 -1
- package/dist/components/hero/context.d.ts +2 -2
- package/dist/components/hero/index.d.ts +2 -2
- package/dist/components/hero/subtitle.d.ts +3 -3
- package/dist/components/hero/title.d.ts +2 -2
- package/dist/components/hotkey/context.d.ts +4 -4
- package/dist/components/hotkey/index.d.ts +2 -2
- package/dist/components/hotkey/set.d.ts +2 -2
- package/dist/components/icon/context.d.ts +4 -4
- package/dist/components/icon/index.d.ts +2 -2
- package/dist/components/input/context.d.ts +2 -2
- package/dist/components/input/index.d.ts +2 -2
- package/dist/components/kanban/card-body.d.ts +2 -2
- package/dist/components/kanban/card-header-actions.d.ts +2 -2
- package/dist/components/kanban/card-header-title.d.ts +2 -2
- package/dist/components/kanban/card-header.d.ts +2 -2
- package/dist/components/kanban/card.d.ts +2 -2
- package/dist/components/kanban/column-actions.d.ts +2 -2
- package/dist/components/kanban/column-container.d.ts +2 -2
- package/dist/components/kanban/column-content.d.ts +2 -2
- package/dist/components/kanban/column-header-actions.d.ts +2 -2
- package/dist/components/kanban/column-header-drag-handle.d.ts +2 -2
- package/dist/components/kanban/column-header-title.d.ts +2 -2
- package/dist/components/kanban/column-header.d.ts +2 -2
- package/dist/components/kanban/column.d.ts +2 -2
- package/dist/components/kanban/context.d.ts +2 -2
- package/dist/components/kanban/header-actions.d.ts +2 -2
- package/dist/components/kanban/header-search.d.ts +2 -2
- package/dist/components/kanban/header-title.d.ts +2 -2
- package/dist/components/kanban/header.d.ts +2 -2
- package/dist/components/kanban/kanban.d.ts +4 -4
- package/dist/components/label/context.d.ts +4 -4
- package/dist/components/label/index.d.ts +2 -2
- package/dist/components/lines/index.d.ts +2 -2
- package/dist/components/link/context.d.ts +2 -2
- package/dist/components/link/index.d.ts +2 -2
- package/dist/components/list/context.d.ts +2 -2
- package/dist/components/list/index.d.ts +2 -2
- package/dist/components/list/item-content.d.ts +2 -2
- package/dist/components/list/item-description.d.ts +2 -2
- package/dist/components/list/item-title.d.ts +2 -2
- package/dist/components/list/item.d.ts +2 -2
- package/dist/components/media-controls/context.d.ts +4 -4
- package/dist/components/media-controls/fullscreen-button.d.ts +2 -2
- package/dist/components/media-controls/index.d.ts +2 -2
- package/dist/components/media-controls/mute-button.d.ts +2 -2
- package/dist/components/media-controls/play-button.d.ts +2 -2
- package/dist/components/media-controls/playback-rate.d.ts +2 -2
- package/dist/components/media-controls/seek-button.d.ts +2 -2
- package/dist/components/media-controls/time-display.d.ts +2 -2
- package/dist/components/media-controls/time-range.d.ts +2 -2
- package/dist/components/media-controls/volume-slider.d.ts +2 -2
- package/dist/components/menu/context.d.ts +2 -2
- package/dist/components/menu/index.d.ts +2 -2
- package/dist/components/menu/item-description.d.ts +2 -2
- package/dist/components/menu/item-label.d.ts +2 -2
- package/dist/components/menu/item.d.ts +2 -2
- package/dist/components/menu/section.d.ts +2 -2
- package/dist/components/menu/separator.d.ts +2 -2
- package/dist/components/menu/submenu.d.ts +2 -2
- package/dist/components/notice/index.d.ts +2 -2
- package/dist/components/notice/list.d.ts +2 -2
- package/dist/components/notice/notice-icon.d.ts +2 -2
- package/dist/components/options/context.d.ts +2 -2
- package/dist/components/options/index.d.ts +2 -2
- package/dist/components/options/item-content.d.ts +2 -2
- package/dist/components/options/item-description.d.ts +2 -2
- package/dist/components/options/item-label.d.ts +2 -2
- package/dist/components/options/item.d.ts +2 -2
- package/dist/components/options/section.d.ts +2 -2
- package/dist/components/pagination/context.d.ts +2 -2
- package/dist/components/pagination/index.d.ts +2 -2
- package/dist/components/pagination/next.d.ts +2 -2
- package/dist/components/pagination/pages.d.ts +2 -2
- package/dist/components/pagination/prev.d.ts +2 -2
- package/dist/components/popover/content.d.ts +2 -2
- package/dist/components/popover/footer.d.ts +2 -2
- package/dist/components/popover/index.d.ts +2 -2
- package/dist/components/popover/title.d.ts +2 -2
- package/dist/components/popover/trigger.d.ts +2 -2
- package/dist/components/query-builder/action-element.d.ts +2 -2
- package/dist/components/query-builder/actions.d.ts +4 -4
- package/dist/components/query-builder/combinator-selector.d.ts +2 -2
- package/dist/components/query-builder/index.d.ts +2 -2
- package/dist/components/query-builder/rule-group.d.ts +4 -4
- package/dist/components/query-builder/rule.d.ts +2 -2
- package/dist/components/query-builder/value-editor.d.ts +2 -2
- package/dist/components/query-builder/value-selector.d.ts +2 -2
- package/dist/components/radio/context.d.ts +3 -3
- package/dist/components/radio/group.d.ts +2 -2
- package/dist/components/radio/index.d.ts +2 -2
- package/dist/components/search-field/context.d.ts +4 -4
- package/dist/components/search-field/index.d.ts +2 -2
- package/dist/components/select-field/context.d.ts +4 -4
- package/dist/components/select-field/index.d.ts +2 -2
- package/dist/components/sidenav/avatar.d.ts +2 -2
- package/dist/components/sidenav/content.d.ts +2 -2
- package/dist/components/sidenav/context.d.ts +2 -2
- package/dist/components/sidenav/footer.d.ts +2 -2
- package/dist/components/sidenav/header.d.ts +2 -2
- package/dist/components/sidenav/index.d.ts +2 -2
- package/dist/components/sidenav/item.d.ts +2 -2
- package/dist/components/sidenav/link.d.ts +2 -2
- package/dist/components/sidenav/menu-item.d.ts +2 -2
- package/dist/components/sidenav/menu.d.ts +2 -2
- package/dist/components/sidenav/trigger.d.ts +2 -2
- package/dist/components/skeleton/index.d.ts +2 -2
- package/dist/components/slider/index.d.ts +2 -2
- package/dist/components/status-indicator/index.d.ts +2 -2
- package/dist/components/switch/context.d.ts +4 -4
- package/dist/components/switch/index.d.ts +2 -2
- package/dist/components/table/body.d.ts +4 -3
- package/dist/components/table/body.js.map +1 -1
- package/dist/components/table/cell.d.ts +4 -3
- package/dist/components/table/cell.js.map +1 -1
- package/dist/components/table/context.d.ts +2 -2
- package/dist/components/table/features.d.ts +80 -0
- package/dist/components/table/features.js +61 -0
- package/dist/components/table/features.js.map +1 -0
- package/dist/components/table/header-cell.d.ts +4 -3
- package/dist/components/table/header-cell.js.map +1 -1
- package/dist/components/table/header.d.ts +4 -3
- package/dist/components/table/header.js.map +1 -1
- package/dist/components/table/index.d.ts +2 -2
- package/dist/components/table/index.js +40 -49
- package/dist/components/table/index.js.map +1 -1
- package/dist/components/table/row-ordering-feature.d.ts +88 -0
- package/dist/components/table/row-ordering-feature.js +115 -0
- package/dist/components/table/row-ordering-feature.js.map +1 -0
- package/dist/components/table/row.d.ts +4 -3
- package/dist/components/table/row.js.map +1 -1
- package/dist/components/table/types.d.ts +15 -13
- package/dist/components/tabs/context.d.ts +3 -3
- package/dist/components/tabs/index.d.ts +2 -2
- package/dist/components/tabs/list.d.ts +2 -2
- package/dist/components/tabs/panel.d.ts +2 -2
- package/dist/components/tabs/tab.d.ts +2 -2
- package/dist/components/text-area-field/context.d.ts +4 -4
- package/dist/components/text-area-field/index.d.ts +2 -2
- package/dist/components/text-field/context.d.ts +4 -4
- package/dist/components/text-field/index.d.ts +2 -2
- package/dist/components/time-field/index.d.ts +2 -2
- package/dist/components/tooltip/context.d.ts +2 -2
- package/dist/components/tooltip/index.d.ts +2 -2
- package/dist/components/tooltip/trigger.d.ts +2 -2
- package/dist/components/tree/context.d.ts +3 -3
- package/dist/components/tree/index.d.ts +2 -2
- package/dist/components/tree/item-actions.d.ts +2 -2
- package/dist/components/tree/item-content.d.ts +2 -2
- package/dist/components/tree/item-description.d.ts +2 -2
- package/dist/components/tree/item-label.d.ts +2 -2
- package/dist/components/tree/item-prefix-icon.d.ts +2 -2
- package/dist/components/tree/item.d.ts +2 -2
- package/dist/components/tree/lines.d.ts +2 -2
- package/dist/components/video/index.d.ts +2 -2
- package/dist/components/view-stack/context.d.ts +2 -2
- package/dist/components/view-stack/index.d.ts +2 -2
- package/dist/components/view-stack/trigger.d.ts +2 -2
- package/dist/components/view-stack/view.d.ts +2 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/providers/portal.d.ts +2 -2
- package/dist/providers/theme-provider.d.ts +2 -2
- package/package.json +20 -14
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at https://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { Bounds, Dimensions, FloatingCardLayout, Position } from "./types.js";
|
|
14
|
+
import { ReactNode, RefCallback } from "react";
|
|
15
|
+
import * as react_jsx_runtime98 from "react/jsx-runtime";
|
|
16
|
+
import { UniqueId } from "@accelint/core/utility/uuid";
|
|
17
|
+
|
|
18
|
+
//#region src/components/floating-card/panel.d.ts
|
|
19
|
+
type FloatingCardPanelProps = {
|
|
20
|
+
/** Identifier of the card this panel renders. */
|
|
21
|
+
id: UniqueId;
|
|
22
|
+
/** Current geometry and stacking order. */
|
|
23
|
+
layout: FloatingCardLayout;
|
|
24
|
+
/** Whether the card is pinned, which freezes drag and resize. */
|
|
25
|
+
isPinned: boolean;
|
|
26
|
+
/** Header content rendered before the title. */
|
|
27
|
+
header: ReactNode;
|
|
28
|
+
/** Header content rendered after the title, typically actions. */
|
|
29
|
+
actions: ReactNode;
|
|
30
|
+
/** Reads the provider's box so gestures can be constrained to it. */
|
|
31
|
+
getBounds: () => Bounds;
|
|
32
|
+
/** Registers the portal target that card children render into. */
|
|
33
|
+
contentRef: RefCallback<HTMLDivElement>;
|
|
34
|
+
/** Raises this card above its siblings. */
|
|
35
|
+
onFocus: () => void;
|
|
36
|
+
/** Commits a new position during a drag. */
|
|
37
|
+
onMove: (position: Position) => void;
|
|
38
|
+
/** Commits new geometry during a resize. */
|
|
39
|
+
onResize: (dimensions: Dimensions, position: Position) => void;
|
|
40
|
+
/** Accessible name for the card, taken from its title. */
|
|
41
|
+
label: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Renders one floating card: its chrome, its drag surface, and the portal
|
|
45
|
+
* target its children mount into.
|
|
46
|
+
*
|
|
47
|
+
* @param props - {@link FloatingCardPanelProps}
|
|
48
|
+
* @returns The positioned card element.
|
|
49
|
+
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* Presentational only -- all geometry is owned by the provider and passed in,
|
|
52
|
+
* so this component stays a pure function of its props.
|
|
53
|
+
*/
|
|
54
|
+
declare function FloatingCardPanel({
|
|
55
|
+
id,
|
|
56
|
+
layout,
|
|
57
|
+
isPinned,
|
|
58
|
+
header,
|
|
59
|
+
actions,
|
|
60
|
+
getBounds,
|
|
61
|
+
contentRef,
|
|
62
|
+
onFocus,
|
|
63
|
+
onMove,
|
|
64
|
+
onResize,
|
|
65
|
+
label
|
|
66
|
+
}: FloatingCardPanelProps): react_jsx_runtime98.JSX.Element;
|
|
67
|
+
//#endregion
|
|
68
|
+
export { FloatingCardPanel, FloatingCardPanelProps };
|
|
69
|
+
//# sourceMappingURL=panel.d.ts.map
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at https://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
import { useDrag } from "./hooks/use-drag.js";
|
|
15
|
+
import { useResize } from "./hooks/use-resize.js";
|
|
16
|
+
import { useCallback, useMemo } from "react";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
import styles from "./styles.module.css";
|
|
19
|
+
|
|
20
|
+
//#region src/components/floating-card/panel.tsx
|
|
21
|
+
/** Handles rendered around the card, paired with the cursor each one shows. */
|
|
22
|
+
const RESIZE_HANDLES = [
|
|
23
|
+
"n",
|
|
24
|
+
"s",
|
|
25
|
+
"e",
|
|
26
|
+
"w",
|
|
27
|
+
"ne",
|
|
28
|
+
"nw",
|
|
29
|
+
"se",
|
|
30
|
+
"sw"
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Renders one floating card: its chrome, its drag surface, and the portal
|
|
34
|
+
* target its children mount into.
|
|
35
|
+
*
|
|
36
|
+
* @param props - {@link FloatingCardPanelProps}
|
|
37
|
+
* @returns The positioned card element.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Presentational only -- all geometry is owned by the provider and passed in,
|
|
41
|
+
* so this component stays a pure function of its props.
|
|
42
|
+
*/
|
|
43
|
+
function FloatingCardPanel({ id, layout, isPinned, header, actions, getBounds, contentRef, onFocus, onMove, onResize, label }) {
|
|
44
|
+
const { position, dimensions, zIndex } = layout;
|
|
45
|
+
const { handleStart } = useDrag({
|
|
46
|
+
disabled: isPinned,
|
|
47
|
+
position,
|
|
48
|
+
dimensions,
|
|
49
|
+
getBounds,
|
|
50
|
+
onPositionChange: onMove,
|
|
51
|
+
onDragStart: onFocus
|
|
52
|
+
});
|
|
53
|
+
const { getHandleProps } = useResize({
|
|
54
|
+
disabled: isPinned,
|
|
55
|
+
position,
|
|
56
|
+
dimensions,
|
|
57
|
+
getBounds,
|
|
58
|
+
onResize,
|
|
59
|
+
onResizeStart: onFocus
|
|
60
|
+
});
|
|
61
|
+
const handleHeaderPointerDown = useCallback((event) => {
|
|
62
|
+
onFocus();
|
|
63
|
+
handleStart(event.nativeEvent);
|
|
64
|
+
}, [handleStart, onFocus]);
|
|
65
|
+
const style = useMemo(() => ({
|
|
66
|
+
left: position.x,
|
|
67
|
+
top: position.y,
|
|
68
|
+
width: dimensions.width,
|
|
69
|
+
height: dimensions.height,
|
|
70
|
+
zIndex
|
|
71
|
+
}), [
|
|
72
|
+
position.x,
|
|
73
|
+
position.y,
|
|
74
|
+
dimensions.width,
|
|
75
|
+
dimensions.height,
|
|
76
|
+
zIndex
|
|
77
|
+
]);
|
|
78
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
79
|
+
"aria-label": label,
|
|
80
|
+
"aria-modal": "false",
|
|
81
|
+
className: styles.panel,
|
|
82
|
+
"data-pinned": isPinned || void 0,
|
|
83
|
+
onPointerDown: onFocus,
|
|
84
|
+
role: "dialog",
|
|
85
|
+
style,
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ jsxs("div", {
|
|
88
|
+
className: styles.header,
|
|
89
|
+
onPointerDown: handleHeaderPointerDown,
|
|
90
|
+
children: [header, /* @__PURE__ */ jsx("div", {
|
|
91
|
+
className: styles.headerActions,
|
|
92
|
+
children: actions
|
|
93
|
+
})]
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ jsx("div", {
|
|
96
|
+
className: styles.content,
|
|
97
|
+
ref: contentRef
|
|
98
|
+
}),
|
|
99
|
+
isPinned ? null : RESIZE_HANDLES.map((handle) => /* @__PURE__ */ jsx("div", {
|
|
100
|
+
"aria-hidden": "true",
|
|
101
|
+
className: styles[`resize-${handle}`],
|
|
102
|
+
"data-handle": handle,
|
|
103
|
+
...getHandleProps(handle)
|
|
104
|
+
}, `${id}-resize-${handle}`))
|
|
105
|
+
]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
//#endregion
|
|
110
|
+
export { FloatingCardPanel };
|
|
111
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","names":["RESIZE_HANDLES: readonly ResizeHandle[]"],"sources":["../../../src/components/floating-card/panel.tsx"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useDrag } from './hooks/use-drag';\nimport { useResize } from './hooks/use-resize';\nimport styles from './styles.module.css';\nimport type { UniqueId } from '@accelint/core/utility/uuid';\nimport type { ReactNode, RefCallback } from 'react';\nimport type {\n Bounds,\n Dimensions,\n FloatingCardLayout,\n Position,\n ResizeHandle,\n} from './types';\n\n/** Handles rendered around the card, paired with the cursor each one shows. */\nconst RESIZE_HANDLES: readonly ResizeHandle[] = [\n 'n',\n 's',\n 'e',\n 'w',\n 'ne',\n 'nw',\n 'se',\n 'sw',\n];\n\nexport type FloatingCardPanelProps = {\n /** Identifier of the card this panel renders. */\n id: UniqueId;\n /** Current geometry and stacking order. */\n layout: FloatingCardLayout;\n /** Whether the card is pinned, which freezes drag and resize. */\n isPinned: boolean;\n /** Header content rendered before the title. */\n header: ReactNode;\n /** Header content rendered after the title, typically actions. */\n actions: ReactNode;\n /** Reads the provider's box so gestures can be constrained to it. */\n getBounds: () => Bounds;\n /** Registers the portal target that card children render into. */\n contentRef: RefCallback<HTMLDivElement>;\n /** Raises this card above its siblings. */\n onFocus: () => void;\n /** Commits a new position during a drag. */\n onMove: (position: Position) => void;\n /** Commits new geometry during a resize. */\n onResize: (dimensions: Dimensions, position: Position) => void;\n /** Accessible name for the card, taken from its title. */\n label: string;\n};\n\n/**\n * Renders one floating card: its chrome, its drag surface, and the portal\n * target its children mount into.\n *\n * @param props - {@link FloatingCardPanelProps}\n * @returns The positioned card element.\n *\n * @remarks\n * Presentational only -- all geometry is owned by the provider and passed in,\n * so this component stays a pure function of its props.\n */\nexport function FloatingCardPanel({\n id,\n layout,\n isPinned,\n header,\n actions,\n getBounds,\n contentRef,\n onFocus,\n onMove,\n onResize,\n label,\n}: FloatingCardPanelProps) {\n const { position, dimensions, zIndex } = layout;\n\n const { handleStart } = useDrag({\n disabled: isPinned,\n position,\n dimensions,\n getBounds,\n onPositionChange: onMove,\n onDragStart: onFocus,\n });\n\n const { getHandleProps } = useResize({\n disabled: isPinned,\n position,\n dimensions,\n getBounds,\n onResize,\n onResizeStart: onFocus,\n });\n\n const handleHeaderPointerDown = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onFocus();\n handleStart(event.nativeEvent);\n },\n [handleStart, onFocus],\n );\n\n const style = useMemo(\n () => ({\n left: position.x,\n top: position.y,\n width: dimensions.width,\n height: dimensions.height,\n zIndex,\n }),\n [position.x, position.y, dimensions.width, dimensions.height, zIndex],\n );\n\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: pointerdown only raises the card; every control inside stays keyboard reachable.\n <div\n aria-label={label}\n // Cards coexist with the rest of the application rather than blocking it,\n // so the dialog is explicitly non-modal.\n aria-modal='false'\n className={styles.panel}\n data-pinned={isPinned || undefined}\n onPointerDown={onFocus}\n role='dialog'\n style={style}\n >\n <div className={styles.header} onPointerDown={handleHeaderPointerDown}>\n {header}\n <div className={styles.headerActions}>{actions}</div>\n </div>\n\n <div className={styles.content} ref={contentRef} />\n\n {isPinned\n ? null\n : RESIZE_HANDLES.map((handle) => (\n <div\n aria-hidden='true'\n className={styles[`resize-${handle}`]}\n data-handle={handle}\n key={`${id}-resize-${handle}`}\n {...getHandleProps(handle)}\n />\n ))}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA4BA,MAAMA,iBAA0C;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;;;;;;;AAsCD,SAAgB,kBAAkB,EAChC,IACA,QACA,UACA,QACA,SACA,WACA,YACA,SACA,QACA,UACA,SACyB;CACzB,MAAM,EAAE,UAAU,YAAY,WAAW;CAEzC,MAAM,EAAE,gBAAgB,QAAQ;EAC9B,UAAU;EACV;EACA;EACA;EACA,kBAAkB;EAClB,aAAa;EACd,CAAC;CAEF,MAAM,EAAE,mBAAmB,UAAU;EACnC,UAAU;EACV;EACA;EACA;EACA;EACA,eAAe;EAChB,CAAC;CAEF,MAAM,0BAA0B,aAC7B,UAA8C;AAC7C,WAAS;AACT,cAAY,MAAM,YAAY;IAEhC,CAAC,aAAa,QAAQ,CACvB;CAED,MAAM,QAAQ,eACL;EACL,MAAM,SAAS;EACf,KAAK,SAAS;EACd,OAAO,WAAW;EAClB,QAAQ,WAAW;EACnB;EACD,GACD;EAAC,SAAS;EAAG,SAAS;EAAG,WAAW;EAAO,WAAW;EAAQ;EAAO,CACtE;AAED,QAEE,qBAAC;EACC,cAAY;EAGZ,cAAW;EACX,WAAW,OAAO;EAClB,eAAa,YAAY;EACzB,eAAe;EACf,MAAK;EACE;;GAEP,qBAAC;IAAI,WAAW,OAAO;IAAQ,eAAe;eAC3C,QACD,oBAAC;KAAI,WAAW,OAAO;eAAgB;MAAc;KACjD;GAEN,oBAAC;IAAI,WAAW,OAAO;IAAS,KAAK;KAAc;GAElD,WACG,OACA,eAAe,KAAK,WAClB,oBAAC;IACC,eAAY;IACZ,WAAW,OAAO,UAAU;IAC5B,eAAa;IAEb,GAAI,eAAe,OAAO;MADrB,GAAG,GAAG,UAAU,SAErB,CACF;;GACF"}
|
|
@@ -11,28 +11,31 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { FloatingCardProviderProps } from "./types.js";
|
|
14
|
-
import * as
|
|
14
|
+
import * as react_jsx_runtime99 from "react/jsx-runtime";
|
|
15
15
|
|
|
16
16
|
//#region src/components/floating-card/provider.d.ts
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Provides a context and layout area for floating cards within the application.
|
|
20
20
|
*
|
|
21
|
-
* Wraps children with floating card context and renders
|
|
22
|
-
*
|
|
21
|
+
* Wraps children with floating card context and renders each registered card as
|
|
22
|
+
* a draggable, resizable panel bounded by the provider's own box.
|
|
23
23
|
*
|
|
24
24
|
* @param props - The props for the FloatingCardProvider component.
|
|
25
25
|
* @param props.children - Child components rendered inside the floating card provider.
|
|
26
26
|
* @param props.icon - Optional icon rendered in all card headers (static or factory).
|
|
27
27
|
* @param props.headerActions - Optional action buttons for card headers (static or factory).
|
|
28
|
+
* @param props.initialPinned - Card IDs that start pinned.
|
|
29
|
+
* @param props.bounds - Region cards are confined to. Defaults to `'provider'`.
|
|
28
30
|
* @param props.className - Additional CSS class names for styling.
|
|
29
31
|
* @returns The FloatingCardProvider component that manages floating card layout and context.
|
|
30
32
|
*
|
|
31
33
|
* @remarks
|
|
32
34
|
* - Manages registration and cleanup of floating card DOM references
|
|
33
35
|
* - Exposes closeCard, togglePinCard, and isPinned via context
|
|
34
|
-
* -
|
|
35
|
-
*
|
|
36
|
+
* - Cards are bounded within the provider element by default; `bounds='viewport'`
|
|
37
|
+
* lets them move anywhere on screen
|
|
38
|
+
* - Cards are dragged by their header; pinning a card freezes drag and resize
|
|
36
39
|
*
|
|
37
40
|
* @example
|
|
38
41
|
* ```tsx
|
|
@@ -55,8 +58,9 @@ declare function FloatingCardProvider({
|
|
|
55
58
|
icon,
|
|
56
59
|
headerActions,
|
|
57
60
|
initialPinned,
|
|
61
|
+
bounds,
|
|
58
62
|
className
|
|
59
|
-
}: FloatingCardProviderProps):
|
|
63
|
+
}: FloatingCardProviderProps): react_jsx_runtime99.JSX.Element;
|
|
60
64
|
//#endregion
|
|
61
65
|
export { FloatingCardProvider };
|
|
62
66
|
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -14,55 +14,26 @@
|
|
|
14
14
|
import { Icon } from "../icon/index.js";
|
|
15
15
|
import { Button } from "../button/index.js";
|
|
16
16
|
import { Divider } from "../divider/index.js";
|
|
17
|
-
import { FloatingCardContext,
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
17
|
+
import { FloatingCardContext, FloatingCardRegistryContext } from "./context.js";
|
|
18
|
+
import { useCardLayout } from "./hooks/use-card-layout.js";
|
|
19
|
+
import { FloatingCardPanel } from "./panel.js";
|
|
20
|
+
import { resolveMaybeFactory } from "./utils.js";
|
|
21
|
+
import { useCallback, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
20
22
|
import { clsx } from "@accelint/design-foundation/lib/utils";
|
|
21
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
23
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
22
24
|
import Cancel from "@accelint/icons/cancel";
|
|
23
25
|
import PinIcon from "@accelint/icons/pin";
|
|
24
|
-
import { DockviewReact } from "dockview-react";
|
|
25
26
|
import styles from "./styles.module.css";
|
|
26
27
|
|
|
27
28
|
//#region src/components/floating-card/provider.tsx
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
* Used by the floating card engine to mount portal targets. Also manages
|
|
32
|
-
* the data-pinned attribute on the resize container to control drag handle visibility.
|
|
33
|
-
*
|
|
34
|
-
* @param props - Dockview panel props containing the card ID.
|
|
35
|
-
*/
|
|
36
|
-
function FloatingCardContainer(props) {
|
|
37
|
-
const { addRef, isPinned, subscribeToPinState } = useFloatingCard();
|
|
38
|
-
const cardId = props.api.id;
|
|
39
|
-
const pinned = useSyncExternalStore(subscribeToPinState, () => isPinned(cardId), () => false);
|
|
40
|
-
const cardRef = useRef(null);
|
|
41
|
-
const refCallback = useCallback((ref) => {
|
|
42
|
-
cardRef.current = ref;
|
|
43
|
-
addRef(cardId, ref);
|
|
44
|
-
}, [addRef, cardId]);
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
const container = cardRef.current?.closest(".dv-resize-container");
|
|
47
|
-
if (!container) return;
|
|
48
|
-
if (pinned) container.dataset.pinned = "";
|
|
49
|
-
else delete container.dataset.pinned;
|
|
50
|
-
}, [pinned]);
|
|
51
|
-
return /* @__PURE__ */ jsx("div", {
|
|
52
|
-
className: styles.cardContent,
|
|
53
|
-
ref: refCallback
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Default left header showing an optional custom icon and the card's title.
|
|
58
|
-
*/
|
|
59
|
-
function DefaultLeftHeader({ title, icon, id }) {
|
|
29
|
+
/** Header shown at the start of a card: optional icon plus the title. */
|
|
30
|
+
function CardHeaderStart({ icon, title }) {
|
|
60
31
|
return /* @__PURE__ */ jsxs("div", {
|
|
61
32
|
className: styles.headerSide,
|
|
62
33
|
children: [icon ? /* @__PURE__ */ jsx(Icon, {
|
|
63
34
|
size: "small",
|
|
64
35
|
children: icon
|
|
65
|
-
}) : null, title
|
|
36
|
+
}) : null, title ? /* @__PURE__ */ jsx("div", {
|
|
66
37
|
className: styles.headerTitleContainer,
|
|
67
38
|
children: /* @__PURE__ */ jsx("div", {
|
|
68
39
|
className: styles.headerTitle,
|
|
@@ -71,64 +42,55 @@ function DefaultLeftHeader({ title, icon, id }) {
|
|
|
71
42
|
}) : null]
|
|
72
43
|
});
|
|
73
44
|
}
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
className: styles.headerSide,
|
|
85
|
-
children: [headerActions?.map((action, index) => {
|
|
86
|
-
if (action === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, `${id}-divider-${index}`);
|
|
87
|
-
if (action === "pin") return /* @__PURE__ */ jsx(Button, {
|
|
88
|
-
className: styles.pinButton,
|
|
89
|
-
variant: "icon",
|
|
90
|
-
size: "small",
|
|
91
|
-
color: pinned ? "accent" : void 0,
|
|
92
|
-
"aria-label": "Pin",
|
|
93
|
-
"aria-pressed": pinned,
|
|
94
|
-
onClick: () => {
|
|
95
|
-
if (id && togglePinCard) togglePinCard(id);
|
|
96
|
-
},
|
|
97
|
-
children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PinIcon, {}) })
|
|
98
|
-
}, `${id}-pin-${index}`);
|
|
99
|
-
return /* @__PURE__ */ jsx(Button, {
|
|
100
|
-
variant: "icon",
|
|
101
|
-
size: "small",
|
|
102
|
-
onClick: action.onClick,
|
|
103
|
-
children: /* @__PURE__ */ jsx(Icon, { children: action.icon })
|
|
104
|
-
}, `${id}-${index}`);
|
|
105
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
45
|
+
/** Action buttons for a card, ending in the always-present close button. */
|
|
46
|
+
function CardHeaderActions({ actions, id, isPinned, onClose, onTogglePin }) {
|
|
47
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [actions?.map((action, index) => {
|
|
48
|
+
if (action === "divider") return /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }, `${id}-divider-${index}`);
|
|
49
|
+
if (action === "pin") return /* @__PURE__ */ jsx(Button, {
|
|
50
|
+
"aria-label": "Pin",
|
|
51
|
+
"aria-pressed": isPinned,
|
|
52
|
+
color: isPinned ? "accent" : void 0,
|
|
53
|
+
onPress: onTogglePin,
|
|
54
|
+
size: "small",
|
|
106
55
|
variant: "icon",
|
|
56
|
+
children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PinIcon, {}) })
|
|
57
|
+
}, `${id}-pin-${index}`);
|
|
58
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
59
|
+
"aria-label": action.label,
|
|
60
|
+
onPress: action.onClick,
|
|
107
61
|
size: "small",
|
|
108
|
-
|
|
109
|
-
children: /* @__PURE__ */ jsx(Icon, { children:
|
|
110
|
-
})
|
|
111
|
-
})
|
|
62
|
+
variant: "icon",
|
|
63
|
+
children: /* @__PURE__ */ jsx(Icon, { children: action.icon })
|
|
64
|
+
}, `${id}-action-${index}`);
|
|
65
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
66
|
+
"aria-label": "Close",
|
|
67
|
+
onPress: onClose,
|
|
68
|
+
size: "small",
|
|
69
|
+
variant: "icon",
|
|
70
|
+
children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Cancel, {}) })
|
|
71
|
+
})] });
|
|
112
72
|
}
|
|
113
|
-
const components = { default: FloatingCardContainer };
|
|
114
73
|
/**
|
|
115
74
|
* Provides a context and layout area for floating cards within the application.
|
|
116
75
|
*
|
|
117
|
-
* Wraps children with floating card context and renders
|
|
118
|
-
*
|
|
76
|
+
* Wraps children with floating card context and renders each registered card as
|
|
77
|
+
* a draggable, resizable panel bounded by the provider's own box.
|
|
119
78
|
*
|
|
120
79
|
* @param props - The props for the FloatingCardProvider component.
|
|
121
80
|
* @param props.children - Child components rendered inside the floating card provider.
|
|
122
81
|
* @param props.icon - Optional icon rendered in all card headers (static or factory).
|
|
123
82
|
* @param props.headerActions - Optional action buttons for card headers (static or factory).
|
|
83
|
+
* @param props.initialPinned - Card IDs that start pinned.
|
|
84
|
+
* @param props.bounds - Region cards are confined to. Defaults to `'provider'`.
|
|
124
85
|
* @param props.className - Additional CSS class names for styling.
|
|
125
86
|
* @returns The FloatingCardProvider component that manages floating card layout and context.
|
|
126
87
|
*
|
|
127
88
|
* @remarks
|
|
128
89
|
* - Manages registration and cleanup of floating card DOM references
|
|
129
90
|
* - Exposes closeCard, togglePinCard, and isPinned via context
|
|
130
|
-
* -
|
|
131
|
-
*
|
|
91
|
+
* - Cards are bounded within the provider element by default; `bounds='viewport'`
|
|
92
|
+
* lets them move anywhere on screen
|
|
93
|
+
* - Cards are dragged by their header; pinning a card freezes drag and resize
|
|
132
94
|
*
|
|
133
95
|
* @example
|
|
134
96
|
* ```tsx
|
|
@@ -146,113 +108,157 @@ const components = { default: FloatingCardContainer };
|
|
|
146
108
|
* </FloatingCardProvider>
|
|
147
109
|
* ```
|
|
148
110
|
*/
|
|
149
|
-
function FloatingCardProvider({ children, icon, headerActions, initialPinned, className }) {
|
|
150
|
-
const
|
|
111
|
+
function FloatingCardProvider({ children, icon, headerActions, initialPinned, bounds = "provider", className }) {
|
|
112
|
+
const rootRef = useRef(null);
|
|
151
113
|
const [cards, setCards] = useState({});
|
|
152
|
-
const
|
|
114
|
+
const pinnedRef = useRef(new Set(initialPinned));
|
|
153
115
|
const pinListenersRef = useRef(/* @__PURE__ */ new Set());
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
}, [api]);
|
|
157
|
-
const togglePinCard = useCallback((id) => {
|
|
158
|
-
const next = new Set(pinnedCardsRef.current);
|
|
159
|
-
if (next.has(id)) next.delete(id);
|
|
160
|
-
else next.add(id);
|
|
161
|
-
pinnedCardsRef.current = next;
|
|
116
|
+
const { layouts, registerCard, unregisterCard, moveCard, resizeCard, bringToFront } = useCardLayout();
|
|
117
|
+
const notifyPinChange = useCallback(() => {
|
|
162
118
|
for (const listener of pinListenersRef.current) listener();
|
|
163
119
|
}, []);
|
|
164
|
-
const isPinned = useCallback((id) =>
|
|
120
|
+
const isPinned = useCallback((id) => pinnedRef.current.has(id), []);
|
|
165
121
|
const subscribeToPinState = useCallback((callback) => {
|
|
166
122
|
pinListenersRef.current.add(callback);
|
|
167
123
|
return () => {
|
|
168
124
|
pinListenersRef.current.delete(callback);
|
|
169
125
|
};
|
|
170
126
|
}, []);
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
127
|
+
const togglePinCard = useCallback((id) => {
|
|
128
|
+
const next = new Set(pinnedRef.current);
|
|
129
|
+
if (next.has(id)) next.delete(id);
|
|
130
|
+
else next.add(id);
|
|
131
|
+
pinnedRef.current = next;
|
|
132
|
+
notifyPinChange();
|
|
133
|
+
}, [notifyPinChange]);
|
|
134
|
+
const removeRef = useCallback((id) => {
|
|
135
|
+
setCards((current) => {
|
|
136
|
+
if (!current[id]) return current;
|
|
137
|
+
const next = { ...current };
|
|
138
|
+
delete next[id];
|
|
139
|
+
return next;
|
|
176
140
|
});
|
|
177
|
-
if (
|
|
178
|
-
const next = new Set(
|
|
179
|
-
next.delete(
|
|
180
|
-
|
|
181
|
-
|
|
141
|
+
if (pinnedRef.current.has(id)) {
|
|
142
|
+
const next = new Set(pinnedRef.current);
|
|
143
|
+
next.delete(id);
|
|
144
|
+
pinnedRef.current = next;
|
|
145
|
+
notifyPinChange();
|
|
182
146
|
}
|
|
183
|
-
}, []);
|
|
147
|
+
}, [notifyPinChange]);
|
|
184
148
|
const addRef = useCallback((id, ref) => {
|
|
185
|
-
if (ref)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
[id]: ref
|
|
190
|
-
};
|
|
149
|
+
if (!ref) return;
|
|
150
|
+
setCards((current) => current[id] === ref ? current : {
|
|
151
|
+
...current,
|
|
152
|
+
[id]: ref
|
|
191
153
|
});
|
|
192
154
|
}, []);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
155
|
+
const closeCard = useCallback((id) => {
|
|
156
|
+
unregisterCard(id);
|
|
157
|
+
removeRef(id);
|
|
158
|
+
}, [removeRef, unregisterCard]);
|
|
159
|
+
const getBounds = useCallback(() => {
|
|
160
|
+
const element = rootRef.current;
|
|
161
|
+
if (!element) return {
|
|
162
|
+
top: 0,
|
|
163
|
+
left: 0,
|
|
164
|
+
right: 0,
|
|
165
|
+
bottom: 0
|
|
166
|
+
};
|
|
167
|
+
const rect = element.getBoundingClientRect();
|
|
168
|
+
if (bounds === "viewport") return {
|
|
169
|
+
top: -rect.top,
|
|
170
|
+
left: -rect.left,
|
|
171
|
+
right: window.innerWidth - rect.left,
|
|
172
|
+
bottom: window.innerHeight - rect.top
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
top: 0,
|
|
176
|
+
left: 0,
|
|
177
|
+
right: rect.width,
|
|
178
|
+
bottom: rect.height
|
|
200
179
|
};
|
|
201
|
-
}, [
|
|
180
|
+
}, [bounds]);
|
|
202
181
|
const contextValue = useMemo(() => ({
|
|
203
182
|
cards,
|
|
204
|
-
addRef,
|
|
205
|
-
removeRef,
|
|
206
183
|
closeCard,
|
|
207
184
|
togglePinCard,
|
|
208
185
|
isPinned,
|
|
209
|
-
subscribeToPinState
|
|
210
|
-
api
|
|
186
|
+
subscribeToPinState
|
|
211
187
|
}), [
|
|
212
188
|
cards,
|
|
213
189
|
closeCard,
|
|
214
|
-
removeRef,
|
|
215
|
-
api,
|
|
216
|
-
addRef,
|
|
217
190
|
togglePinCard,
|
|
218
191
|
isPinned,
|
|
219
192
|
subscribeToPinState
|
|
220
193
|
]);
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
isPinned,
|
|
226
|
-
subscribeToPinState
|
|
227
|
-
}), [
|
|
228
|
-
headerActions,
|
|
229
|
-
togglePinCard,
|
|
230
|
-
isPinned,
|
|
231
|
-
subscribeToPinState
|
|
232
|
-
]);
|
|
233
|
-
const theme = useMemo(() => ({
|
|
234
|
-
name: "accelint",
|
|
235
|
-
className: styles.floatingCardProvider ?? ""
|
|
236
|
-
}), []);
|
|
237
|
-
const onReady = useCallback((event) => {
|
|
238
|
-
setApi(event.api);
|
|
239
|
-
}, []);
|
|
194
|
+
const registryValue = useMemo(() => ({
|
|
195
|
+
openCard: registerCard,
|
|
196
|
+
addRef
|
|
197
|
+
}), [registerCard, addRef]);
|
|
240
198
|
return /* @__PURE__ */ jsx(FloatingCardContext.Provider, {
|
|
241
199
|
value: contextValue,
|
|
242
|
-
children: /* @__PURE__ */
|
|
243
|
-
|
|
244
|
-
children:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
200
|
+
children: /* @__PURE__ */ jsx(FloatingCardRegistryContext.Provider, {
|
|
201
|
+
value: registryValue,
|
|
202
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
203
|
+
className: clsx(styles.providerRoot, className),
|
|
204
|
+
ref: rootRef,
|
|
205
|
+
children: [Object.entries(layouts).map(([id, layout]) => /* @__PURE__ */ jsx(CardPanel, {
|
|
206
|
+
actions: resolveMaybeFactory(headerActions, id),
|
|
207
|
+
getBounds,
|
|
208
|
+
icon: resolveMaybeFactory(icon, id),
|
|
209
|
+
id,
|
|
210
|
+
isPinned,
|
|
211
|
+
layout,
|
|
212
|
+
onAddRef: addRef,
|
|
213
|
+
onClose: closeCard,
|
|
214
|
+
onFocus: bringToFront,
|
|
215
|
+
onMove: moveCard,
|
|
216
|
+
onResize: resizeCard,
|
|
217
|
+
onTogglePin: togglePinCard,
|
|
218
|
+
subscribeToPinState
|
|
219
|
+
}, id)), children]
|
|
220
|
+
})
|
|
253
221
|
})
|
|
254
222
|
});
|
|
255
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Binds one card's identity to the provider's callbacks so {@link FloatingCardPanel}
|
|
226
|
+
* can stay a plain presentational component.
|
|
227
|
+
*
|
|
228
|
+
* @remarks
|
|
229
|
+
* Pin state lives in a mutable store rather than React state, so it is read
|
|
230
|
+
* through `useSyncExternalStore` -- only the cards whose pin state changed
|
|
231
|
+
* re-render.
|
|
232
|
+
*/
|
|
233
|
+
function CardPanel({ actions, getBounds, icon, id, isPinned, layout, onAddRef, onClose, onFocus, onMove, onResize, onTogglePin, subscribeToPinState }) {
|
|
234
|
+
const { title } = layout;
|
|
235
|
+
const pinned = useSyncExternalStore(subscribeToPinState, () => isPinned(id), () => false);
|
|
236
|
+
const contentRef = useCallback((element) => {
|
|
237
|
+
onAddRef(id, element);
|
|
238
|
+
}, [id, onAddRef]);
|
|
239
|
+
return /* @__PURE__ */ jsx(FloatingCardPanel, {
|
|
240
|
+
actions: /* @__PURE__ */ jsx(CardHeaderActions, {
|
|
241
|
+
actions,
|
|
242
|
+
id,
|
|
243
|
+
isPinned: pinned,
|
|
244
|
+
onClose: () => onClose(id),
|
|
245
|
+
onTogglePin: () => onTogglePin(id)
|
|
246
|
+
}),
|
|
247
|
+
contentRef,
|
|
248
|
+
getBounds,
|
|
249
|
+
header: /* @__PURE__ */ jsx(CardHeaderStart, {
|
|
250
|
+
icon,
|
|
251
|
+
title
|
|
252
|
+
}),
|
|
253
|
+
id,
|
|
254
|
+
isPinned: pinned,
|
|
255
|
+
label: title ?? "Floating card",
|
|
256
|
+
layout,
|
|
257
|
+
onFocus: () => onFocus(id),
|
|
258
|
+
onMove: (position) => onMove(id, position),
|
|
259
|
+
onResize: (dimensions, position) => onResize(id, dimensions, position)
|
|
260
|
+
});
|
|
261
|
+
}
|
|
256
262
|
|
|
257
263
|
//#endregion
|
|
258
264
|
export { FloatingCardProvider };
|