@salt-ds/lab 1.0.0-alpha.91 → 1.0.0-alpha.93
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/CHANGELOG.md +21 -0
- package/css/salt-lab.css +24 -142
- package/dist-cjs/index.js +0 -16
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/tree/Tree.js +4 -1
- package/dist-cjs/tree/Tree.js.map +1 -1
- package/dist-cjs/tree/TreeNode.css.js +1 -1
- package/dist-cjs/tree/TreeNodeExpansionIcon.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-es/index.js +0 -8
- package/dist-es/index.js.map +1 -1
- package/dist-es/tree/Tree.js +4 -1
- package/dist-es/tree/Tree.js.map +1 -1
- package/dist-es/tree/TreeNode.css.js +1 -1
- package/dist-es/tree/TreeNodeExpansionIcon.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-types/index.d.ts +0 -1
- package/package.json +2 -2
- package/dist-cjs/side-panel/SidePanel.css.js +0 -6
- package/dist-cjs/side-panel/SidePanel.css.js.map +0 -1
- package/dist-cjs/side-panel/SidePanel.js +0 -151
- package/dist-cjs/side-panel/SidePanel.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelCloseButton.js +0 -38
- package/dist-cjs/side-panel/SidePanelCloseButton.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelContent.css.js +0 -6
- package/dist-cjs/side-panel/SidePanelContent.css.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelContent.js +0 -66
- package/dist-cjs/side-panel/SidePanelContent.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelHeader.css.js +0 -6
- package/dist-cjs/side-panel/SidePanelHeader.css.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelHeader.js +0 -26
- package/dist-cjs/side-panel/SidePanelHeader.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelProvider.js +0 -89
- package/dist-cjs/side-panel/SidePanelProvider.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelTitle.css.js +0 -6
- package/dist-cjs/side-panel/SidePanelTitle.css.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelTitle.js +0 -48
- package/dist-cjs/side-panel/SidePanelTitle.js.map +0 -1
- package/dist-cjs/side-panel/SidePanelTrigger.js +0 -37
- package/dist-cjs/side-panel/SidePanelTrigger.js.map +0 -1
- package/dist-cjs/side-panel/internal/SidePanelContext.js +0 -34
- package/dist-cjs/side-panel/internal/SidePanelContext.js.map +0 -1
- package/dist-cjs/side-panel/internal/useIsScrollable.js +0 -50
- package/dist-cjs/side-panel/internal/useIsScrollable.js.map +0 -1
- package/dist-cjs/side-panel/internal/useSidePanelTabOrder.js +0 -121
- package/dist-cjs/side-panel/internal/useSidePanelTabOrder.js.map +0 -1
- package/dist-cjs/side-panel/useSidePanel.js +0 -43
- package/dist-cjs/side-panel/useSidePanel.js.map +0 -1
- package/dist-es/side-panel/SidePanel.css.js +0 -4
- package/dist-es/side-panel/SidePanel.css.js.map +0 -1
- package/dist-es/side-panel/SidePanel.js +0 -149
- package/dist-es/side-panel/SidePanel.js.map +0 -1
- package/dist-es/side-panel/SidePanelCloseButton.js +0 -36
- package/dist-es/side-panel/SidePanelCloseButton.js.map +0 -1
- package/dist-es/side-panel/SidePanelContent.css.js +0 -4
- package/dist-es/side-panel/SidePanelContent.css.js.map +0 -1
- package/dist-es/side-panel/SidePanelContent.js +0 -64
- package/dist-es/side-panel/SidePanelContent.js.map +0 -1
- package/dist-es/side-panel/SidePanelHeader.css.js +0 -4
- package/dist-es/side-panel/SidePanelHeader.css.js.map +0 -1
- package/dist-es/side-panel/SidePanelHeader.js +0 -24
- package/dist-es/side-panel/SidePanelHeader.js.map +0 -1
- package/dist-es/side-panel/SidePanelProvider.js +0 -87
- package/dist-es/side-panel/SidePanelProvider.js.map +0 -1
- package/dist-es/side-panel/SidePanelTitle.css.js +0 -4
- package/dist-es/side-panel/SidePanelTitle.css.js.map +0 -1
- package/dist-es/side-panel/SidePanelTitle.js +0 -46
- package/dist-es/side-panel/SidePanelTitle.js.map +0 -1
- package/dist-es/side-panel/SidePanelTrigger.js +0 -35
- package/dist-es/side-panel/SidePanelTrigger.js.map +0 -1
- package/dist-es/side-panel/internal/SidePanelContext.js +0 -31
- package/dist-es/side-panel/internal/SidePanelContext.js.map +0 -1
- package/dist-es/side-panel/internal/useIsScrollable.js +0 -48
- package/dist-es/side-panel/internal/useIsScrollable.js.map +0 -1
- package/dist-es/side-panel/internal/useSidePanelTabOrder.js +0 -119
- package/dist-es/side-panel/internal/useSidePanelTabOrder.js.map +0 -1
- package/dist-es/side-panel/useSidePanel.js +0 -41
- package/dist-es/side-panel/useSidePanel.js.map +0 -1
- package/dist-types/side-panel/SidePanel.d.ts +0 -27
- package/dist-types/side-panel/SidePanelCloseButton.d.ts +0 -2
- package/dist-types/side-panel/SidePanelContent.d.ts +0 -4
- package/dist-types/side-panel/SidePanelHeader.d.ts +0 -4
- package/dist-types/side-panel/SidePanelProvider.d.ts +0 -20
- package/dist-types/side-panel/SidePanelTitle.d.ts +0 -4
- package/dist-types/side-panel/SidePanelTrigger.d.ts +0 -4
- package/dist-types/side-panel/index.d.ts +0 -8
- package/dist-types/side-panel/internal/SidePanelContext.d.ts +0 -56
- package/dist-types/side-panel/internal/index.d.ts +0 -3
- package/dist-types/side-panel/internal/useIsScrollable.d.ts +0 -2
- package/dist-types/side-panel/internal/useSidePanelTabOrder.d.ts +0 -7
- package/dist-types/side-panel/useSidePanel.d.ts +0 -39
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelContext.js","sources":["../src/side-panel/internal/SidePanelContext.ts"],"sourcesContent":["import type { FloatingRootContext } from \"@floating-ui/react\";\nimport { createContext } from \"@salt-ds/core\";\nimport { type Dispatch, type SetStateAction, useContext } from \"react\";\n\nexport interface SidePanelContextValue {\n /**\n * Whether the side panel is currently open.\n */\n openState: boolean;\n /**\n * The floating-ui root context shared between the trigger and the panel.\n * Coordinates interactions (click, dismiss, role) across both elements.\n */\n floatingRootContext: FloatingRootContext;\n /**\n * Ref setter for the panel element.\n * Registers the panel DOM node with floating-ui.\n */\n setFloating: Dispatch<SetStateAction<HTMLDivElement | null>>;\n /**\n * Ref setter for the reference (trigger) element.\n * Registers the trigger DOM node with floating-ui for focus return.\n */\n setReference: Dispatch<SetStateAction<HTMLElement | null>>;\n /**\n * Sets the open state of the panel.\n * Called by the close button in SidePanelHeader, or any consumer that needs to close the panel.\n */\n setOpen: (open: boolean) => void;\n /**\n * Side panel id used for aria-controls on the trigger.\n */\n panelId?: string;\n /**\n * Registers or clears the side panel id used for aria-controls/id linkage.\n */\n setPanelId: Dispatch<SetStateAction<string | undefined>>;\n /**\n * The auto-generated id placed on SidePanelTitle.\n * Used for aria-labelledby on the panel region and the scrollable body.\n */\n titleId?: string;\n /**\n * Registers the title id from SidePanelTitle back to the context\n * so that SidePanel and SidePanelContent can use it for aria-labelledby.\n */\n setTitleId: Dispatch<SetStateAction<string | undefined>>;\n /**\n * Edge the panel is anchored to.\n */\n position?: \"right\" | \"left\";\n /**\n * Registers the position from SidePanel back to the context.\n */\n setPosition: Dispatch<SetStateAction<\"right\" | \"left\" | undefined>>;\n}\n\nexport const SidePanelContext = createContext<SidePanelContextValue>(\n \"SidePanelContext\",\n {\n openState: false,\n floatingRootContext: {} as FloatingRootContext,\n setFloating: () => {},\n setReference: () => {},\n setOpen: () => {},\n panelId: undefined,\n setPanelId: () => {},\n titleId: undefined,\n setTitleId: () => {},\n position: undefined,\n setPosition: () => {},\n },\n);\n\nexport function useSidePanelContext() {\n return useContext(SidePanelContext);\n}\n"],"names":["createContext","useContext"],"mappings":";;;;;AAyDO,MAAM,gBAAA,GAAmBA,kBAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AAAA,IACE,SAAA,EAAW,KAAA;AAAA,IACX,qBAAqB,EAAC;AAAA,IACtB,aAAa,MAAM;AAAA,IAAC,CAAA;AAAA,IACpB,cAAc,MAAM;AAAA,IAAC,CAAA;AAAA,IACrB,SAAS,MAAM;AAAA,IAAC,CAAA;AAAA,IAChB,OAAA,EAAS,MAAA;AAAA,IACT,YAAY,MAAM;AAAA,IAAC,CAAA;AAAA,IACnB,OAAA,EAAS,MAAA;AAAA,IACT,YAAY,MAAM;AAAA,IAAC,CAAA;AAAA,IACnB,QAAA,EAAU,MAAA;AAAA,IACV,aAAa,MAAM;AAAA,IAAC;AAAA;AAExB;AAEO,SAAS,mBAAA,GAAsB;AACpC,EAAA,OAAOC,iBAAW,gBAAgB,CAAA;AACpC;;;;;"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var react = require('react');
|
|
4
|
-
|
|
5
|
-
const observedAttributes = ["class", "hidden", "style"];
|
|
6
|
-
function useIsScrollable(ref) {
|
|
7
|
-
const [isScrollable, setIsScrollable] = react.useState(false);
|
|
8
|
-
react.useEffect(() => {
|
|
9
|
-
const element = ref.current;
|
|
10
|
-
const win = element == null ? void 0 : element.ownerDocument.defaultView;
|
|
11
|
-
if (!element || !win) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
let animationFrame;
|
|
15
|
-
const checkScrollable = () => {
|
|
16
|
-
animationFrame = void 0;
|
|
17
|
-
const nextIsScrollable = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
|
|
18
|
-
setIsScrollable(
|
|
19
|
-
(currentIsScrollable) => currentIsScrollable === nextIsScrollable ? currentIsScrollable : nextIsScrollable
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
const scheduleCheck = () => {
|
|
23
|
-
if (animationFrame === void 0) {
|
|
24
|
-
animationFrame = win.requestAnimationFrame(checkScrollable);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
scheduleCheck();
|
|
28
|
-
const resizeObserver = win.ResizeObserver ? new win.ResizeObserver(scheduleCheck) : void 0;
|
|
29
|
-
resizeObserver == null ? void 0 : resizeObserver.observe(element);
|
|
30
|
-
const mutationObserver = win.MutationObserver ? new win.MutationObserver(scheduleCheck) : void 0;
|
|
31
|
-
mutationObserver == null ? void 0 : mutationObserver.observe(element, {
|
|
32
|
-
attributeFilter: observedAttributes,
|
|
33
|
-
attributes: true,
|
|
34
|
-
characterData: true,
|
|
35
|
-
childList: true,
|
|
36
|
-
subtree: true
|
|
37
|
-
});
|
|
38
|
-
return () => {
|
|
39
|
-
if (animationFrame !== void 0) {
|
|
40
|
-
win.cancelAnimationFrame(animationFrame);
|
|
41
|
-
}
|
|
42
|
-
resizeObserver == null ? void 0 : resizeObserver.disconnect();
|
|
43
|
-
mutationObserver == null ? void 0 : mutationObserver.disconnect();
|
|
44
|
-
};
|
|
45
|
-
}, [ref]);
|
|
46
|
-
return isScrollable;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
exports.useIsScrollable = useIsScrollable;
|
|
50
|
-
//# sourceMappingURL=useIsScrollable.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useIsScrollable.js","sources":["../src/side-panel/internal/useIsScrollable.ts"],"sourcesContent":["import { type RefObject, useEffect, useState } from \"react\";\n\nconst observedAttributes = [\"class\", \"hidden\", \"style\"];\n\nexport function useIsScrollable(ref: RefObject<HTMLElement>) {\n const [isScrollable, setIsScrollable] = useState(false);\n\n useEffect(() => {\n const element = ref.current;\n const win = element?.ownerDocument.defaultView;\n if (!element || !win) {\n return;\n }\n\n let animationFrame: number | undefined;\n\n const checkScrollable = () => {\n animationFrame = undefined;\n const nextIsScrollable =\n element.scrollHeight > element.clientHeight ||\n element.scrollWidth > element.clientWidth;\n\n setIsScrollable((currentIsScrollable) =>\n currentIsScrollable === nextIsScrollable\n ? currentIsScrollable\n : nextIsScrollable,\n );\n };\n\n const scheduleCheck = () => {\n if (animationFrame === undefined) {\n animationFrame = win.requestAnimationFrame(checkScrollable);\n }\n };\n\n scheduleCheck();\n\n const resizeObserver = win.ResizeObserver\n ? new win.ResizeObserver(scheduleCheck)\n : undefined;\n resizeObserver?.observe(element);\n\n const mutationObserver = win.MutationObserver\n ? new win.MutationObserver(scheduleCheck)\n : undefined;\n mutationObserver?.observe(element, {\n attributeFilter: observedAttributes,\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n\n return () => {\n if (animationFrame !== undefined) {\n win.cancelAnimationFrame(animationFrame);\n }\n resizeObserver?.disconnect();\n mutationObserver?.disconnect();\n };\n }, [ref]);\n\n return isScrollable;\n}\n"],"names":["useState","useEffect"],"mappings":";;;;AAEA,MAAM,kBAAA,GAAqB,CAAC,OAAA,EAAS,QAAA,EAAU,OAAO,CAAA;AAE/C,SAAS,gBAAgB,GAAA,EAA6B;AAC3D,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,eAAS,KAAK,CAAA;AAEtD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,UAAU,GAAA,CAAI,OAAA;AACpB,IAAA,MAAM,GAAA,GAAM,mCAAS,aAAA,CAAc,WAAA;AACnC,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,GAAA,EAAK;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,cAAA;AAEJ,IAAA,MAAM,kBAAkB,MAAM;AAC5B,MAAA,cAAA,GAAiB,MAAA;AACjB,MAAA,MAAM,mBACJ,OAAA,CAAQ,YAAA,GAAe,QAAQ,YAAA,IAC/B,OAAA,CAAQ,cAAc,OAAA,CAAQ,WAAA;AAEhC,MAAA,eAAA;AAAA,QAAgB,CAAC,mBAAA,KACf,mBAAA,KAAwB,gBAAA,GACpB,mBAAA,GACA;AAAA,OACN;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,gBAAgB,MAAM;AAC1B,MAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,QAAA,cAAA,GAAiB,GAAA,CAAI,sBAAsB,eAAe,CAAA;AAAA,MAC5D;AAAA,IACF,CAAA;AAEA,IAAA,aAAA,EAAc;AAEd,IAAA,MAAM,iBAAiB,GAAA,CAAI,cAAA,GACvB,IAAI,GAAA,CAAI,cAAA,CAAe,aAAa,CAAA,GACpC,MAAA;AACJ,IAAA,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAgB,OAAA,CAAQ,OAAA,CAAA;AAExB,IAAA,MAAM,mBAAmB,GAAA,CAAI,gBAAA,GACzB,IAAI,GAAA,CAAI,gBAAA,CAAiB,aAAa,CAAA,GACtC,MAAA;AACJ,IAAA,gBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,gBAAA,CAAkB,QAAQ,OAAA,EAAS;AAAA,MACjC,eAAA,EAAiB,kBAAA;AAAA,MACjB,UAAA,EAAY,IAAA;AAAA,MACZ,aAAA,EAAe,IAAA;AAAA,MACf,SAAA,EAAW,IAAA;AAAA,MACX,OAAA,EAAS;AAAA,KACX,CAAA;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,QAAA,GAAA,CAAI,qBAAqB,cAAc,CAAA;AAAA,MACzC;AACA,MAAA,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAgB,UAAA,EAAA;AAChB,MAAA,gBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,gBAAA,CAAkB,UAAA,EAAA;AAAA,IACpB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,OAAO,YAAA;AACT;;;;"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var react = require('react');
|
|
4
|
-
var tabbable = require('tabbable');
|
|
5
|
-
|
|
6
|
-
function isPlainTabKey(event) {
|
|
7
|
-
return event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey;
|
|
8
|
-
}
|
|
9
|
-
function getPanelTabbableElements(panel) {
|
|
10
|
-
return tabbable.tabbable(panel);
|
|
11
|
-
}
|
|
12
|
-
function focusFirstPanelElement(panel) {
|
|
13
|
-
const [firstTabbableElement] = getPanelTabbableElements(panel);
|
|
14
|
-
(firstTabbableElement ?? panel).focus();
|
|
15
|
-
}
|
|
16
|
-
function focusLastPanelElement(panel) {
|
|
17
|
-
const tabbableElements = getPanelTabbableElements(panel);
|
|
18
|
-
(tabbableElements[tabbableElements.length - 1] ?? panel).focus();
|
|
19
|
-
}
|
|
20
|
-
function containsTarget(container, target) {
|
|
21
|
-
const targetWindow = container.ownerDocument.defaultView;
|
|
22
|
-
return Boolean(
|
|
23
|
-
(targetWindow == null ? void 0 : targetWindow.Node) && target instanceof targetWindow.Node && container.contains(target)
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
function getNextTabbableAfterReference(reference, panel) {
|
|
27
|
-
const { body } = reference.ownerDocument;
|
|
28
|
-
const tabbableElements = tabbable.tabbable(body).filter(
|
|
29
|
-
(element) => !panel.contains(element)
|
|
30
|
-
);
|
|
31
|
-
const referenceIndex = tabbableElements.findIndex(
|
|
32
|
-
(element) => element === reference || reference.contains(element)
|
|
33
|
-
);
|
|
34
|
-
if (referenceIndex === -1) {
|
|
35
|
-
return void 0;
|
|
36
|
-
}
|
|
37
|
-
return tabbableElements[referenceIndex + 1];
|
|
38
|
-
}
|
|
39
|
-
function useSidePanelTabOrder(props) {
|
|
40
|
-
const { floating, open, reference } = props;
|
|
41
|
-
const followsReferenceOrder = react.useRef(false);
|
|
42
|
-
react.useEffect(() => {
|
|
43
|
-
if (!open || !reference || !floating) {
|
|
44
|
-
followsReferenceOrder.current = false;
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const { ownerDocument } = reference;
|
|
48
|
-
const onReferenceKeyDown = (event) => {
|
|
49
|
-
if (event.defaultPrevented || !isPlainTabKey(event) || event.shiftKey) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
followsReferenceOrder.current = true;
|
|
54
|
-
focusFirstPanelElement(floating);
|
|
55
|
-
};
|
|
56
|
-
const onFloatingKeyDown = (event) => {
|
|
57
|
-
if (event.defaultPrevented || !isPlainTabKey(event)) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const panelTabbableElements = getPanelTabbableElements(floating);
|
|
61
|
-
const activeElement = floating.ownerDocument.activeElement;
|
|
62
|
-
if (event.shiftKey) {
|
|
63
|
-
const firstPanelElement = panelTabbableElements[0] ?? floating;
|
|
64
|
-
if (activeElement === firstPanelElement && followsReferenceOrder.current) {
|
|
65
|
-
event.preventDefault();
|
|
66
|
-
followsReferenceOrder.current = false;
|
|
67
|
-
reference.focus();
|
|
68
|
-
}
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const lastPanelElement = panelTabbableElements[panelTabbableElements.length - 1] ?? floating;
|
|
72
|
-
if (activeElement === lastPanelElement && followsReferenceOrder.current) {
|
|
73
|
-
const nextElement = getNextTabbableAfterReference(reference, floating);
|
|
74
|
-
if (nextElement) {
|
|
75
|
-
event.preventDefault();
|
|
76
|
-
followsReferenceOrder.current = false;
|
|
77
|
-
nextElement.focus();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const onDocumentKeyDown = (event) => {
|
|
82
|
-
if (event.defaultPrevented || !isPlainTabKey(event) || !event.shiftKey) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const nextElement = getNextTabbableAfterReference(reference, floating);
|
|
86
|
-
if (!nextElement || !containsTarget(nextElement, event.target)) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
followsReferenceOrder.current = true;
|
|
91
|
-
focusLastPanelElement(floating);
|
|
92
|
-
};
|
|
93
|
-
const onFloatingFocusIn = (event) => {
|
|
94
|
-
if (containsTarget(reference, event.relatedTarget)) {
|
|
95
|
-
followsReferenceOrder.current = true;
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const nextElement = getNextTabbableAfterReference(reference, floating);
|
|
99
|
-
if (nextElement && containsTarget(nextElement, event.relatedTarget)) {
|
|
100
|
-
followsReferenceOrder.current = true;
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (!containsTarget(floating, event.relatedTarget)) {
|
|
104
|
-
followsReferenceOrder.current = false;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
reference.addEventListener("keydown", onReferenceKeyDown);
|
|
108
|
-
floating.addEventListener("keydown", onFloatingKeyDown);
|
|
109
|
-
floating.addEventListener("focusin", onFloatingFocusIn);
|
|
110
|
-
ownerDocument.addEventListener("keydown", onDocumentKeyDown);
|
|
111
|
-
return () => {
|
|
112
|
-
reference.removeEventListener("keydown", onReferenceKeyDown);
|
|
113
|
-
floating.removeEventListener("keydown", onFloatingKeyDown);
|
|
114
|
-
floating.removeEventListener("focusin", onFloatingFocusIn);
|
|
115
|
-
ownerDocument.removeEventListener("keydown", onDocumentKeyDown);
|
|
116
|
-
};
|
|
117
|
-
}, [floating, open, reference]);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
exports.useSidePanelTabOrder = useSidePanelTabOrder;
|
|
121
|
-
//# sourceMappingURL=useSidePanelTabOrder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSidePanelTabOrder.js","sources":["../src/side-panel/internal/useSidePanelTabOrder.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { tabbable } from \"tabbable\";\n\ninterface UseSidePanelTabOrderProps {\n floating: HTMLElement | null;\n open: boolean;\n reference: HTMLElement | null;\n}\n\nfunction isPlainTabKey(event: KeyboardEvent) {\n return (\n event.key === \"Tab\" && !event.altKey && !event.ctrlKey && !event.metaKey\n );\n}\n\nfunction getPanelTabbableElements(panel: HTMLElement) {\n return tabbable(panel);\n}\n\nfunction focusFirstPanelElement(panel: HTMLElement) {\n const [firstTabbableElement] = getPanelTabbableElements(panel);\n (firstTabbableElement ?? panel).focus();\n}\n\nfunction focusLastPanelElement(panel: HTMLElement) {\n const tabbableElements = getPanelTabbableElements(panel);\n (tabbableElements[tabbableElements.length - 1] ?? panel).focus();\n}\n\nfunction containsTarget(container: Element, target: EventTarget | null) {\n const targetWindow = container.ownerDocument.defaultView;\n\n return Boolean(\n targetWindow?.Node &&\n target instanceof targetWindow.Node &&\n container.contains(target),\n );\n}\n\nfunction getNextTabbableAfterReference(\n reference: HTMLElement,\n panel: HTMLElement,\n) {\n const { body } = reference.ownerDocument;\n const tabbableElements = tabbable(body).filter(\n (element) => !panel.contains(element),\n );\n const referenceIndex = tabbableElements.findIndex(\n (element) => element === reference || reference.contains(element),\n );\n\n if (referenceIndex === -1) {\n return undefined;\n }\n\n return tabbableElements[referenceIndex + 1];\n}\n\nexport function useSidePanelTabOrder(props: UseSidePanelTabOrderProps) {\n const { floating, open, reference } = props;\n const followsReferenceOrder = useRef(false);\n\n useEffect(() => {\n if (!open || !reference || !floating) {\n followsReferenceOrder.current = false;\n return;\n }\n\n const { ownerDocument } = reference;\n\n const onReferenceKeyDown = (event: KeyboardEvent) => {\n if (event.defaultPrevented || !isPlainTabKey(event) || event.shiftKey) {\n return;\n }\n\n event.preventDefault();\n followsReferenceOrder.current = true;\n focusFirstPanelElement(floating);\n };\n\n const onFloatingKeyDown = (event: KeyboardEvent) => {\n if (event.defaultPrevented || !isPlainTabKey(event)) {\n return;\n }\n\n const panelTabbableElements = getPanelTabbableElements(floating);\n const activeElement = floating.ownerDocument.activeElement;\n\n if (event.shiftKey) {\n const firstPanelElement = panelTabbableElements[0] ?? floating;\n\n if (\n activeElement === firstPanelElement &&\n followsReferenceOrder.current\n ) {\n event.preventDefault();\n followsReferenceOrder.current = false;\n reference.focus();\n }\n return;\n }\n\n const lastPanelElement =\n panelTabbableElements[panelTabbableElements.length - 1] ?? floating;\n\n if (activeElement === lastPanelElement && followsReferenceOrder.current) {\n const nextElement = getNextTabbableAfterReference(reference, floating);\n\n if (nextElement) {\n event.preventDefault();\n followsReferenceOrder.current = false;\n nextElement.focus();\n }\n }\n };\n\n const onDocumentKeyDown = (event: KeyboardEvent) => {\n if (event.defaultPrevented || !isPlainTabKey(event) || !event.shiftKey) {\n return;\n }\n\n const nextElement = getNextTabbableAfterReference(reference, floating);\n if (!nextElement || !containsTarget(nextElement, event.target)) {\n return;\n }\n\n event.preventDefault();\n followsReferenceOrder.current = true;\n focusLastPanelElement(floating);\n };\n\n const onFloatingFocusIn = (event: FocusEvent) => {\n if (containsTarget(reference, event.relatedTarget)) {\n followsReferenceOrder.current = true;\n return;\n }\n\n const nextElement = getNextTabbableAfterReference(reference, floating);\n if (nextElement && containsTarget(nextElement, event.relatedTarget)) {\n followsReferenceOrder.current = true;\n return;\n }\n\n if (!containsTarget(floating, event.relatedTarget)) {\n followsReferenceOrder.current = false;\n }\n };\n\n reference.addEventListener(\"keydown\", onReferenceKeyDown);\n floating.addEventListener(\"keydown\", onFloatingKeyDown);\n floating.addEventListener(\"focusin\", onFloatingFocusIn);\n ownerDocument.addEventListener(\"keydown\", onDocumentKeyDown);\n\n return () => {\n reference.removeEventListener(\"keydown\", onReferenceKeyDown);\n floating.removeEventListener(\"keydown\", onFloatingKeyDown);\n floating.removeEventListener(\"focusin\", onFloatingFocusIn);\n ownerDocument.removeEventListener(\"keydown\", onDocumentKeyDown);\n };\n }, [floating, open, reference]);\n}\n"],"names":["tabbable","useRef","useEffect"],"mappings":"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"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var react = require('react');
|
|
4
|
-
var SidePanelContext = require('./internal/SidePanelContext.js');
|
|
5
|
-
require('tabbable');
|
|
6
|
-
|
|
7
|
-
function useSidePanel() {
|
|
8
|
-
const { openState, setOpen, setReference, panelId } = SidePanelContext.useSidePanelContext();
|
|
9
|
-
const getTriggerProps = react.useCallback(
|
|
10
|
-
(userProps) => {
|
|
11
|
-
const userOnClick = userProps == null ? void 0 : userProps.onClick;
|
|
12
|
-
return {
|
|
13
|
-
"aria-expanded": openState,
|
|
14
|
-
"aria-controls": openState ? panelId : void 0,
|
|
15
|
-
...userProps,
|
|
16
|
-
onClick: (e) => {
|
|
17
|
-
userOnClick == null ? void 0 : userOnClick(e);
|
|
18
|
-
setOpen(!openState);
|
|
19
|
-
},
|
|
20
|
-
ref: (node) => {
|
|
21
|
-
setReference(node);
|
|
22
|
-
const userRef = userProps == null ? void 0 : userProps.ref;
|
|
23
|
-
if (typeof userRef === "function") {
|
|
24
|
-
userRef(node);
|
|
25
|
-
} else if (userRef && typeof userRef === "object" && "current" in userRef) {
|
|
26
|
-
userRef.current = node;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
},
|
|
31
|
-
[openState, panelId, setReference, setOpen]
|
|
32
|
-
);
|
|
33
|
-
return {
|
|
34
|
-
openState,
|
|
35
|
-
setOpen,
|
|
36
|
-
getTriggerProps,
|
|
37
|
-
setTriggerRef: setReference,
|
|
38
|
-
panelId
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
exports.useSidePanel = useSidePanel;
|
|
43
|
-
//# sourceMappingURL=useSidePanel.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSidePanel.js","sources":["../src/side-panel/useSidePanel.ts"],"sourcesContent":["import {\n type MouseEvent,\n type MutableRefObject,\n type RefCallback,\n useCallback,\n} from \"react\";\nimport { useSidePanelContext } from \"./internal\";\n\nexport interface SidePanelValue {\n /**\n * Whether the side panel is currently open.\n */\n openState: boolean;\n /**\n * Sets the open state of the panel.\n */\n setOpen: (open: boolean) => void;\n /**\n * Props getter for a trigger element outside of `SidePanelTrigger`.\n * Returns `aria-expanded`, `aria-controls`, a `ref` (for focus-return),\n * and an `onClick` that toggles the panel.\n *\n * Spread the result onto a Button to get full trigger behavior:\n * ```tsx\n * <Button {...getTriggerProps()}>Toggle panel</Button>\n * ```\n *\n * You can pass additional props which are merged in. If you provide your\n * own `onClick`, it runs before the built-in toggle.\n *\n * For multi-trigger scenarios (e.g. table rows), use `setTriggerRef` and\n * manage ARIA attributes yourself instead.\n */\n getTriggerProps: (\n userProps?: Record<string, unknown>,\n ) => Record<string, unknown>;\n /**\n * Registers the element that should receive focus when the panel closes.\n * Use this in multi-trigger scenarios (e.g. table rows) where each trigger\n * needs explicit control over which element is the reference.\n */\n setTriggerRef: (element: HTMLElement | null) => void;\n /**\n * The panel's DOM id. Use this for `aria-controls` in multi-trigger\n * scenarios where you manage ARIA attributes yourself.\n */\n panelId: string | undefined;\n}\n\nexport function useSidePanel(): SidePanelValue {\n const { openState, setOpen, setReference, panelId } = useSidePanelContext();\n\n const getTriggerProps = useCallback(\n (userProps?: Record<string, unknown>) => {\n const userOnClick = userProps?.onClick as\n | ((e: MouseEvent<HTMLElement>) => void)\n | undefined;\n\n return {\n \"aria-expanded\": openState,\n \"aria-controls\": openState ? panelId : undefined,\n ...userProps,\n onClick: (e: MouseEvent<HTMLElement>) => {\n userOnClick?.(e);\n setOpen(!openState);\n },\n ref: (node: HTMLElement | null) => {\n // Register this element as the trigger for focus return\n setReference(node);\n // Forward the consumer's ref if provided\n const userRef = userProps?.ref as\n | RefCallback<HTMLElement | null>\n | MutableRefObject<HTMLElement | null>;\n if (typeof userRef === \"function\") {\n userRef(node);\n } else if (\n userRef &&\n typeof userRef === \"object\" &&\n \"current\" in userRef\n ) {\n userRef.current = node;\n }\n },\n };\n },\n [openState, panelId, setReference, setOpen],\n );\n\n return {\n openState,\n setOpen,\n getTriggerProps,\n setTriggerRef: setReference,\n panelId,\n };\n}\n"],"names":["useSidePanelContext","useCallback"],"mappings":";;;;;;AAiDO,SAAS,YAAA,GAA+B;AAC7C,EAAA,MAAM,EAAE,SAAA,EAAW,OAAA,EAAS,YAAA,EAAc,OAAA,KAAYA,oCAAA,EAAoB;AAE1E,EAAA,MAAM,eAAA,GAAkBC,iBAAA;AAAA,IACtB,CAAC,SAAA,KAAwC;AACvC,MAAA,MAAM,cAAc,SAAA,IAAA,IAAA,GAAA,MAAA,GAAA,SAAA,CAAW,OAAA;AAI/B,MAAA,OAAO;AAAA,QACL,eAAA,EAAiB,SAAA;AAAA,QACjB,eAAA,EAAiB,YAAY,OAAA,GAAU,MAAA;AAAA,QACvC,GAAG,SAAA;AAAA,QACH,OAAA,EAAS,CAAC,CAAA,KAA+B;AACvC,UAAA,WAAA,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAc,CAAA,CAAA;AACd,UAAA,OAAA,CAAQ,CAAC,SAAS,CAAA;AAAA,QACpB,CAAA;AAAA,QACA,GAAA,EAAK,CAAC,IAAA,KAA6B;AAEjC,UAAA,YAAA,CAAa,IAAI,CAAA;AAEjB,UAAA,MAAM,UAAU,SAAA,IAAA,IAAA,GAAA,MAAA,GAAA,SAAA,CAAW,GAAA;AAG3B,UAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,YAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,UACd,WACE,OAAA,IACA,OAAO,OAAA,KAAY,QAAA,IACnB,aAAa,OAAA,EACb;AACA,YAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,UACpB;AAAA,QACF;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAA,EAAW,OAAA,EAAS,YAAA,EAAc,OAAO;AAAA,GAC5C;AAEA,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA;AAAA,IACA,aAAA,EAAe,YAAA;AAAA,IACf;AAAA,GACF;AACF;;;;"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var css_248z = ".saltSidePanel {\n background-color: var(--sidePanel-background, var(--salt-container-primary-background));\n --saltSidePanel-width: 300px;\n --sidePanel-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--sidePanel-borderColor, var(--salt-container-primary-borderColor));\n --saltSidePanel-padding: var(--salt-spacing-300);\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n}\n\n.saltSidePanel-primary {\n --sidePanel-background: var(--salt-container-primary-background);\n --sidePanel-borderColor: var(--salt-container-primary-borderColor);\n}\n\n.saltSidePanel-secondary {\n --sidePanel-background: var(--salt-container-secondary-background);\n --sidePanel-borderColor: var(--salt-container-secondary-borderColor);\n}\n\n.saltSidePanel-tertiary {\n --sidePanel-background: var(--salt-container-tertiary-background);\n --sidePanel-borderColor: var(--salt-container-tertiary-borderColor);\n}\n\n.saltSidePanel-left {\n border-right: var(--sidePanel-border);\n}\n.saltSidePanel-right {\n border-left: var(--sidePanel-border);\n}\n\n.saltSidePanel-none {\n --sidePanel-background: none;\n border: none;\n}\n\n.saltSidePanel-none {\n --saltSidePanel-padding: var(--salt-spacing-200);\n}\n\n.saltSidePanel-left,\n.saltSidePanel-right {\n width: var(--saltSidePanel-width);\n height: 100%;\n min-height: 0;\n align-self: stretch;\n}\n\n.saltSidePanel-enterAnimation,\n.saltSidePanel-exitAnimation {\n overflow: hidden;\n}\n\n.saltSidePanel-left.saltSidePanel-enterAnimation,\n.saltSidePanel-right.saltSidePanel-enterAnimation {\n animation: saltSidePanel-expandWidth var(--salt-duration-perceptible) var(--salt-animation-timing-function);\n}\n\n.saltSidePanel-left.saltSidePanel-exitAnimation,\n.saltSidePanel-right.saltSidePanel-exitAnimation {\n animation: saltSidePanel-collapseWidth var(--salt-duration-perceptible) var(--salt-animation-timing-function) both;\n}\n\n.saltSidePanel-exitAnimation {\n pointer-events: none;\n}\n\n.saltSidePanel-inner {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n padding: var(--saltSidePanel-padding);\n}\n\n.saltSidePanel-left .saltSidePanel-inner,\n.saltSidePanel-right .saltSidePanel-inner {\n width: var(--saltSidePanel-width);\n height: 100%;\n}\n\n@keyframes saltSidePanel-expandWidth {\n from {\n width: 0;\n }\n}\n@keyframes saltSidePanel-collapseWidth {\n to {\n width: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .saltSidePanel-left.saltSidePanel-enterAnimation,\n .saltSidePanel-right.saltSidePanel-enterAnimation,\n .saltSidePanel-left.saltSidePanel-exitAnimation,\n .saltSidePanel-right.saltSidePanel-exitAnimation {\n animation: none;\n }\n}\n";
|
|
2
|
-
|
|
3
|
-
export { css_248z as default };
|
|
4
|
-
//# sourceMappingURL=SidePanel.css.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanel.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { FloatingFocusManager } from '@floating-ui/react';
|
|
3
|
-
import { makePrefixer, useId, useFloatingUI, useForkRef, useIsomorphicLayoutEffect } from '@salt-ds/core';
|
|
4
|
-
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
5
|
-
import { useWindow } from '@salt-ds/window';
|
|
6
|
-
import { clsx } from 'clsx';
|
|
7
|
-
import { forwardRef, useMemo, useState, useRef, useEffect } from 'react';
|
|
8
|
-
import { useSidePanelContext, SidePanelContext } from './internal/SidePanelContext.js';
|
|
9
|
-
import 'tabbable';
|
|
10
|
-
import css_248z from './SidePanel.css.js';
|
|
11
|
-
|
|
12
|
-
const withBaseName = makePrefixer("saltSidePanel");
|
|
13
|
-
const SidePanel = forwardRef(
|
|
14
|
-
function SidePanel2(props, ref) {
|
|
15
|
-
const {
|
|
16
|
-
disableAnimation = false,
|
|
17
|
-
position = "right",
|
|
18
|
-
initialFocus,
|
|
19
|
-
variant = "primary",
|
|
20
|
-
children,
|
|
21
|
-
id: idProp,
|
|
22
|
-
className,
|
|
23
|
-
"aria-labelledby": ariaLabelledBy,
|
|
24
|
-
onAnimationEnd,
|
|
25
|
-
...rest
|
|
26
|
-
} = props;
|
|
27
|
-
const sidePanelContext = useSidePanelContext();
|
|
28
|
-
const { openState, floatingRootContext, setFloating, setPanelId, titleId } = sidePanelContext;
|
|
29
|
-
const positionedContext = useMemo(
|
|
30
|
-
() => ({ ...sidePanelContext, position }),
|
|
31
|
-
[sidePanelContext, position]
|
|
32
|
-
);
|
|
33
|
-
const id = useId(idProp);
|
|
34
|
-
const [showComponent, setShowComponent] = useState(openState);
|
|
35
|
-
const [animating, setAnimating] = useState(false);
|
|
36
|
-
const shouldAnimateOpen = useRef(!openState);
|
|
37
|
-
const [skipInitialFocus, setSkipInitialFocus] = useState(() => {
|
|
38
|
-
var _a;
|
|
39
|
-
if (!openState) return false;
|
|
40
|
-
const reference = floatingRootContext.elements.reference;
|
|
41
|
-
if (!(reference instanceof Element)) return true;
|
|
42
|
-
const activeElement = (_a = reference.ownerDocument) == null ? void 0 : _a.activeElement;
|
|
43
|
-
return !activeElement || !reference.contains(activeElement);
|
|
44
|
-
});
|
|
45
|
-
const targetWindow = useWindow();
|
|
46
|
-
useComponentCssInjection({
|
|
47
|
-
testId: "salt-side-panel",
|
|
48
|
-
css: css_248z,
|
|
49
|
-
window: targetWindow
|
|
50
|
-
});
|
|
51
|
-
const { context } = useFloatingUI({
|
|
52
|
-
rootContext: floatingRootContext
|
|
53
|
-
});
|
|
54
|
-
const handleRef = useForkRef(setFloating, ref);
|
|
55
|
-
const handleAnimationEnd = (event) => {
|
|
56
|
-
onAnimationEnd == null ? void 0 : onAnimationEnd(event);
|
|
57
|
-
if (event.currentTarget !== event.target || disableAnimation) return;
|
|
58
|
-
setAnimating(false);
|
|
59
|
-
if (!openState) {
|
|
60
|
-
setShowComponent(false);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
setPanelId(id);
|
|
65
|
-
return () => {
|
|
66
|
-
setPanelId(void 0);
|
|
67
|
-
};
|
|
68
|
-
}, [id, setPanelId]);
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (!openState) {
|
|
71
|
-
setSkipInitialFocus(false);
|
|
72
|
-
}
|
|
73
|
-
}, [openState]);
|
|
74
|
-
useIsomorphicLayoutEffect(() => {
|
|
75
|
-
var _a, _b;
|
|
76
|
-
if (disableAnimation) {
|
|
77
|
-
setShowComponent(openState);
|
|
78
|
-
setAnimating(false);
|
|
79
|
-
if (!openState) shouldAnimateOpen.current = true;
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (!openState) {
|
|
83
|
-
shouldAnimateOpen.current = true;
|
|
84
|
-
}
|
|
85
|
-
if (openState && !shouldAnimateOpen.current) {
|
|
86
|
-
setShowComponent(true);
|
|
87
|
-
setAnimating(false);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const prefersReducedMotion = (_b = (_a = targetWindow == null ? void 0 : targetWindow.matchMedia) == null ? void 0 : _a.call(
|
|
91
|
-
targetWindow,
|
|
92
|
-
"(prefers-reduced-motion: reduce)"
|
|
93
|
-
)) == null ? void 0 : _b.matches;
|
|
94
|
-
if (openState) {
|
|
95
|
-
setShowComponent(true);
|
|
96
|
-
}
|
|
97
|
-
if (prefersReducedMotion) {
|
|
98
|
-
setAnimating(false);
|
|
99
|
-
if (!openState) {
|
|
100
|
-
setShowComponent(false);
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
103
|
-
setAnimating(true);
|
|
104
|
-
}
|
|
105
|
-
}, [openState, targetWindow, disableAnimation]);
|
|
106
|
-
if (!showComponent) return null;
|
|
107
|
-
const resolvedInitialFocus = skipInitialFocus ? -1 : initialFocus ?? 0;
|
|
108
|
-
const panelDiv = /* @__PURE__ */ jsx(
|
|
109
|
-
"div",
|
|
110
|
-
{
|
|
111
|
-
role: "region",
|
|
112
|
-
"aria-labelledby": clsx(ariaLabelledBy, titleId) || void 0,
|
|
113
|
-
ref: handleRef,
|
|
114
|
-
className: clsx(
|
|
115
|
-
withBaseName(),
|
|
116
|
-
{
|
|
117
|
-
[withBaseName(position)]: position,
|
|
118
|
-
[withBaseName(variant)]: variant,
|
|
119
|
-
[withBaseName("enterAnimation")]: !disableAnimation && openState && animating,
|
|
120
|
-
[withBaseName("exitAnimation")]: !disableAnimation && !openState && animating
|
|
121
|
-
},
|
|
122
|
-
className
|
|
123
|
-
),
|
|
124
|
-
onAnimationEnd: handleAnimationEnd,
|
|
125
|
-
tabIndex: -1,
|
|
126
|
-
...rest,
|
|
127
|
-
id,
|
|
128
|
-
children: /* @__PURE__ */ jsx(SidePanelContext.Provider, { value: positionedContext, children: /* @__PURE__ */ jsx("div", { className: withBaseName("inner"), children }) })
|
|
129
|
-
}
|
|
130
|
-
);
|
|
131
|
-
if (openState || animating) {
|
|
132
|
-
return /* @__PURE__ */ jsx(
|
|
133
|
-
FloatingFocusManager,
|
|
134
|
-
{
|
|
135
|
-
context,
|
|
136
|
-
modal: false,
|
|
137
|
-
initialFocus: resolvedInitialFocus,
|
|
138
|
-
closeOnFocusOut: false,
|
|
139
|
-
guards: false,
|
|
140
|
-
children: panelDiv
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
return panelDiv;
|
|
145
|
-
}
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
export { SidePanel };
|
|
149
|
-
//# sourceMappingURL=SidePanel.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanel.js","sources":["../src/side-panel/SidePanel.tsx"],"sourcesContent":["import { FloatingFocusManager } from \"@floating-ui/react\";\nimport {\n makePrefixer,\n useFloatingUI,\n useForkRef,\n useId,\n useIsomorphicLayoutEffect,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type AnimationEvent,\n type ComponentProps,\n type ComponentPropsWithRef,\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { SidePanelContext, useSidePanelContext } from \"./internal\";\nimport sidePanelCss from \"./SidePanel.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanel\");\n\nexport interface SidePanelProps extends ComponentPropsWithRef<\"div\"> {\n /**\n * Disable the panel's own open/close animation.\n * Set to `true` when the parent controls sizing and animation (e.g. inside a splitter).\n * @default false\n */\n disableAnimation?: boolean;\n /**\n * Edge the panel is anchored to; controls animation direction and divider side.\n * @default \"right\"\n */\n position?: \"right\" | \"left\";\n /**\n * Which element receives focus when the panel opens.\n * Pass a number for the tabbable element index (0 = first), or a ref to a specific element.\n * Defaults to the side panel close button.\n */\n initialFocus?: ComponentProps<typeof FloatingFocusManager>[\"initialFocus\"];\n /**\n * The background color palette. Options are 'primary', 'secondary', 'tertiary' and 'none'.\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"none\";\n}\n\nexport const SidePanel = forwardRef<HTMLDivElement, SidePanelProps>(\n function SidePanel(props, ref) {\n const {\n disableAnimation = false,\n position = \"right\",\n initialFocus,\n variant = \"primary\",\n children,\n id: idProp,\n className,\n \"aria-labelledby\": ariaLabelledBy,\n onAnimationEnd,\n ...rest\n } = props;\n\n const sidePanelContext = useSidePanelContext();\n const { openState, floatingRootContext, setFloating, setPanelId, titleId } =\n sidePanelContext;\n const positionedContext = useMemo(\n () => ({ ...sidePanelContext, position }),\n [sidePanelContext, position],\n );\n\n const id = useId(idProp);\n\n const [showComponent, setShowComponent] = useState(openState);\n const [animating, setAnimating] = useState(false);\n const shouldAnimateOpen = useRef(!openState);\n // On first mount while open, skip moving focus when focus did not come from the trigger.\n const [skipInitialFocus, setSkipInitialFocus] = useState(() => {\n if (!openState) return false;\n const reference = floatingRootContext.elements.reference;\n if (!(reference instanceof Element)) return true;\n const activeElement = reference.ownerDocument?.activeElement;\n return !activeElement || !reference.contains(activeElement);\n });\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel\",\n css: sidePanelCss,\n window: targetWindow,\n });\n\n const { context } = useFloatingUI({\n rootContext: floatingRootContext,\n });\n\n const handleRef = useForkRef<HTMLDivElement>(setFloating, ref);\n\n const handleAnimationEnd = (event: AnimationEvent<HTMLDivElement>) => {\n onAnimationEnd?.(event);\n\n if (event.currentTarget !== event.target || disableAnimation) return;\n setAnimating(false);\n if (!openState) {\n setShowComponent(false);\n }\n };\n\n useEffect(() => {\n setPanelId(id);\n return () => {\n setPanelId(undefined);\n };\n }, [id, setPanelId]);\n\n useEffect(() => {\n if (!openState) {\n setSkipInitialFocus(false);\n }\n }, [openState]);\n\n useIsomorphicLayoutEffect(() => {\n if (disableAnimation) {\n setShowComponent(openState);\n setAnimating(false);\n if (!openState) shouldAnimateOpen.current = true;\n return;\n }\n\n if (!openState) {\n shouldAnimateOpen.current = true;\n }\n\n // Don't animate if the panel has never been closed (defaultOpen scenario).\n if (openState && !shouldAnimateOpen.current) {\n setShowComponent(true);\n setAnimating(false);\n return;\n }\n\n const prefersReducedMotion = targetWindow?.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n )?.matches;\n\n if (openState) {\n setShowComponent(true);\n }\n\n if (prefersReducedMotion) {\n setAnimating(false);\n if (!openState) {\n setShowComponent(false);\n }\n } else {\n setAnimating(true);\n }\n }, [openState, targetWindow, disableAnimation]);\n\n if (!showComponent) return null;\n\n const resolvedInitialFocus = skipInitialFocus ? -1 : (initialFocus ?? 0);\n\n const panelDiv = (\n <div\n role=\"region\"\n aria-labelledby={clsx(ariaLabelledBy, titleId) || undefined}\n ref={handleRef}\n className={clsx(\n withBaseName(),\n {\n [withBaseName(position)]: position,\n [withBaseName(variant)]: variant,\n [withBaseName(\"enterAnimation\")]:\n !disableAnimation && openState && animating,\n [withBaseName(\"exitAnimation\")]:\n !disableAnimation && !openState && animating,\n },\n className,\n )}\n onAnimationEnd={handleAnimationEnd}\n tabIndex={-1}\n {...rest}\n id={id}\n >\n <SidePanelContext.Provider value={positionedContext}>\n <div className={withBaseName(\"inner\")}>{children}</div>\n </SidePanelContext.Provider>\n </div>\n );\n\n if (openState || animating) {\n return (\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={resolvedInitialFocus}\n closeOnFocusOut={false}\n guards={false}\n >\n {panelDiv}\n </FloatingFocusManager>\n );\n }\n\n return panelDiv;\n },\n);\n"],"names":["SidePanel","sidePanelCss"],"mappings":"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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { makePrefixer, useIcon, useId, Button } from '@salt-ds/core';
|
|
3
|
-
import { clsx } from 'clsx';
|
|
4
|
-
import { forwardRef } from 'react';
|
|
5
|
-
import { useSidePanelContext } from './internal/SidePanelContext.js';
|
|
6
|
-
import 'tabbable';
|
|
7
|
-
|
|
8
|
-
const withBaseName = makePrefixer("saltSidePanelCloseButton");
|
|
9
|
-
const SidePanelCloseButton = forwardRef(
|
|
10
|
-
function SidePanelCloseButton2({ className, onClick, id: idProp, ...rest }, ref) {
|
|
11
|
-
const { CollapseLeftIcon, CollapseRightIcon } = useIcon();
|
|
12
|
-
const { setOpen, titleId, position } = useSidePanelContext();
|
|
13
|
-
const closeButtonId = useId(idProp);
|
|
14
|
-
const handleClick = (event) => {
|
|
15
|
-
onClick == null ? void 0 : onClick(event);
|
|
16
|
-
setOpen(false);
|
|
17
|
-
};
|
|
18
|
-
return /* @__PURE__ */ jsx(
|
|
19
|
-
Button,
|
|
20
|
-
{
|
|
21
|
-
ref,
|
|
22
|
-
id: closeButtonId,
|
|
23
|
-
"aria-label": "Close",
|
|
24
|
-
"aria-labelledby": titleId ? clsx(closeButtonId, titleId) : void 0,
|
|
25
|
-
appearance: "transparent",
|
|
26
|
-
className: clsx(withBaseName(), className),
|
|
27
|
-
onClick: handleClick,
|
|
28
|
-
...rest,
|
|
29
|
-
children: position === "left" ? /* @__PURE__ */ jsx(CollapseLeftIcon, { "aria-hidden": true }) : /* @__PURE__ */ jsx(CollapseRightIcon, { "aria-hidden": true })
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
export { SidePanelCloseButton };
|
|
36
|
-
//# sourceMappingURL=SidePanelCloseButton.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelCloseButton.js","sources":["../src/side-panel/SidePanelCloseButton.tsx"],"sourcesContent":["import {\n Button,\n type ButtonProps,\n makePrefixer,\n useIcon,\n useId,\n} from \"@salt-ds/core\";\nimport { clsx } from \"clsx\";\nimport { forwardRef, type MouseEvent } from \"react\";\nimport { useSidePanelContext } from \"./internal\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelCloseButton\");\n\nexport const SidePanelCloseButton = forwardRef<HTMLButtonElement, ButtonProps>(\n function SidePanelCloseButton(\n { className, onClick, id: idProp, ...rest },\n ref,\n ) {\n const { CollapseLeftIcon, CollapseRightIcon } = useIcon();\n const { setOpen, titleId, position } = useSidePanelContext();\n const closeButtonId = useId(idProp);\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n setOpen(false);\n };\n\n return (\n <Button\n ref={ref}\n id={closeButtonId}\n aria-label=\"Close\"\n aria-labelledby={titleId ? clsx(closeButtonId, titleId) : undefined}\n appearance=\"transparent\"\n className={clsx(withBaseName(), className)}\n onClick={handleClick}\n {...rest}\n >\n {position === \"left\" ? (\n <CollapseLeftIcon aria-hidden />\n ) : (\n <CollapseRightIcon aria-hidden />\n )}\n </Button>\n );\n },\n);\n"],"names":["SidePanelCloseButton"],"mappings":";;;;;;;AAWA,MAAM,YAAA,GAAe,aAAa,0BAA0B,CAAA;AAErD,MAAM,oBAAA,GAAuB,UAAA;AAAA,EAClC,SAASA,qBAAAA,CACP,EAAE,SAAA,EAAW,OAAA,EAAS,IAAI,MAAA,EAAQ,GAAG,IAAA,EAAK,EAC1C,GAAA,EACA;AACA,IAAA,MAAM,EAAE,gBAAA,EAAkB,iBAAA,EAAkB,GAAI,OAAA,EAAQ;AACxD,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,QAAA,KAAa,mBAAA,EAAoB;AAC3D,IAAA,MAAM,aAAA,GAAgB,MAAM,MAAM,CAAA;AAElC,IAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAyC;AAC5D,MAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAU,KAAA,CAAA;AACV,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,EAAA,EAAI,aAAA;AAAA,QACJ,YAAA,EAAW,OAAA;AAAA,QACX,iBAAA,EAAiB,OAAA,GAAU,IAAA,CAAK,aAAA,EAAe,OAAO,CAAA,GAAI,MAAA;AAAA,QAC1D,UAAA,EAAW,aAAA;AAAA,QACX,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACzC,OAAA,EAAS,WAAA;AAAA,QACR,GAAG,IAAA;AAAA,QAEH,QAAA,EAAA,QAAA,KAAa,MAAA,mBACZ,GAAA,CAAC,gBAAA,EAAA,EAAiB,aAAA,EAAW,MAAC,CAAA,mBAE9B,GAAA,CAAC,iBAAA,EAAA,EAAkB,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA,KAEnC;AAAA,EAEJ;AACF;;;;"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var css_248z = ".saltSidePanelContent {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n.saltSidePanelContent-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n}\n";
|
|
2
|
-
|
|
3
|
-
export { css_248z as default };
|
|
4
|
-
//# sourceMappingURL=SidePanelContent.css.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelContent.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { makePrefixer, useId } from '@salt-ds/core';
|
|
3
|
-
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
|
-
import { useWindow } from '@salt-ds/window';
|
|
5
|
-
import { clsx } from 'clsx';
|
|
6
|
-
import { forwardRef, useRef } from 'react';
|
|
7
|
-
import { useSidePanelContext } from './internal/SidePanelContext.js';
|
|
8
|
-
import { useIsScrollable } from './internal/useIsScrollable.js';
|
|
9
|
-
import 'tabbable';
|
|
10
|
-
import css_248z from './SidePanelContent.css.js';
|
|
11
|
-
|
|
12
|
-
const withBaseName = makePrefixer("saltSidePanelContent");
|
|
13
|
-
const SidePanelContent = forwardRef(function SidePanelContent2(props, ref) {
|
|
14
|
-
const {
|
|
15
|
-
children,
|
|
16
|
-
className,
|
|
17
|
-
"aria-labelledby": ariaLabelledBy,
|
|
18
|
-
"aria-label": ariaLabel,
|
|
19
|
-
...rest
|
|
20
|
-
} = props;
|
|
21
|
-
const { titleId } = useSidePanelContext();
|
|
22
|
-
const targetWindow = useWindow();
|
|
23
|
-
const contentSuffixId = useId();
|
|
24
|
-
const bodyRef = useRef(null);
|
|
25
|
-
const isScrollable = useIsScrollable(bodyRef);
|
|
26
|
-
useComponentCssInjection({
|
|
27
|
-
testId: "salt-side-panel-content",
|
|
28
|
-
css: css_248z,
|
|
29
|
-
window: targetWindow
|
|
30
|
-
});
|
|
31
|
-
const explicitLabelledBy = ariaLabelledBy;
|
|
32
|
-
const explicitLabel = ariaLabel;
|
|
33
|
-
let bodyAriaLabelledBy;
|
|
34
|
-
let bodyAriaLabel;
|
|
35
|
-
if (isScrollable) {
|
|
36
|
-
if (explicitLabelledBy) {
|
|
37
|
-
bodyAriaLabelledBy = explicitLabelledBy;
|
|
38
|
-
} else if (titleId) {
|
|
39
|
-
bodyAriaLabelledBy = clsx(titleId, contentSuffixId) || void 0;
|
|
40
|
-
} else {
|
|
41
|
-
bodyAriaLabel = explicitLabel ?? "Content";
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return /* @__PURE__ */ jsxs("div", { ref, className: clsx(withBaseName(), className), ...rest, children: [
|
|
45
|
-
isScrollable ? /* @__PURE__ */ jsx("span", { id: contentSuffixId, hidden: true, children: "content" }) : null,
|
|
46
|
-
/* @__PURE__ */ jsx(
|
|
47
|
-
"div",
|
|
48
|
-
{
|
|
49
|
-
ref: bodyRef,
|
|
50
|
-
className: withBaseName("body"),
|
|
51
|
-
...isScrollable && {
|
|
52
|
-
role: "region",
|
|
53
|
-
tabIndex: 0,
|
|
54
|
-
"aria-labelledby": bodyAriaLabelledBy,
|
|
55
|
-
"aria-label": bodyAriaLabel
|
|
56
|
-
},
|
|
57
|
-
children
|
|
58
|
-
}
|
|
59
|
-
)
|
|
60
|
-
] });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
export { SidePanelContent };
|
|
64
|
-
//# sourceMappingURL=SidePanelContent.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelContent.js","sources":["../src/side-panel/SidePanelContent.tsx"],"sourcesContent":["import { makePrefixer, useId } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentPropsWithRef, forwardRef, useRef } from \"react\";\nimport { useIsScrollable, useSidePanelContext } from \"./internal\";\nimport sidePanelContentCss from \"./SidePanelContent.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelContent\");\n\nexport interface SidePanelContentProps extends ComponentPropsWithRef<\"div\"> {}\n\nexport const SidePanelContent = forwardRef<\n HTMLDivElement,\n SidePanelContentProps\n>(function SidePanelContent(props, ref) {\n const {\n children,\n className,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-label\": ariaLabel,\n ...rest\n } = props;\n\n const { titleId } = useSidePanelContext();\n const targetWindow = useWindow();\n const contentSuffixId = useId();\n const bodyRef = useRef<HTMLDivElement>(null);\n const isScrollable = useIsScrollable(bodyRef);\n\n useComponentCssInjection({\n testId: \"salt-side-panel-content\",\n css: sidePanelContentCss,\n window: targetWindow,\n });\n\n const explicitLabelledBy = ariaLabelledBy;\n const explicitLabel = ariaLabel;\n\n let bodyAriaLabelledBy: string | undefined;\n let bodyAriaLabel: string | undefined;\n\n if (isScrollable) {\n if (explicitLabelledBy) {\n bodyAriaLabelledBy = explicitLabelledBy;\n } else if (titleId) {\n bodyAriaLabelledBy = clsx(titleId, contentSuffixId) || undefined;\n } else {\n bodyAriaLabel = explicitLabel ?? \"Content\";\n }\n }\n\n return (\n <div ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {isScrollable ? (\n <span id={contentSuffixId} hidden>\n content\n </span>\n ) : null}\n <div\n ref={bodyRef}\n className={withBaseName(\"body\")}\n {...(isScrollable && {\n role: \"region\",\n tabIndex: 0,\n \"aria-labelledby\": bodyAriaLabelledBy,\n \"aria-label\": bodyAriaLabel,\n })}\n >\n {children}\n </div>\n </div>\n );\n});\n"],"names":["SidePanelContent","sidePanelContentCss"],"mappings":";;;;;;;;;;;AAQA,MAAM,YAAA,GAAe,aAAa,sBAAsB,CAAA;AAIjD,MAAM,gBAAA,GAAmB,UAAA,CAG9B,SAASA,iBAAAA,CAAiB,OAAO,GAAA,EAAK;AACtC,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,SAAA;AAAA,IACA,iBAAA,EAAmB,cAAA;AAAA,IACnB,YAAA,EAAc,SAAA;AAAA,IACd,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,mBAAA,EAAoB;AACxC,EAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,EAAA,MAAM,kBAAkB,KAAA,EAAM;AAC9B,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,YAAA,GAAe,gBAAgB,OAAO,CAAA;AAE5C,EAAA,wBAAA,CAAyB;AAAA,IACvB,MAAA,EAAQ,yBAAA;AAAA,IACR,GAAA,EAAKC,QAAA;AAAA,IACL,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,kBAAA,GAAqB,cAAA;AAC3B,EAAA,MAAM,aAAA,GAAgB,SAAA;AAEtB,EAAA,IAAI,kBAAA;AACJ,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,IAAI,kBAAA,EAAoB;AACtB,MAAA,kBAAA,GAAqB,kBAAA;AAAA,IACvB,WAAW,OAAA,EAAS;AAClB,MAAA,kBAAA,GAAqB,IAAA,CAAK,OAAA,EAAS,eAAe,CAAA,IAAK,MAAA;AAAA,IACzD,CAAA,MAAO;AACL,MAAA,aAAA,GAAgB,aAAA,IAAiB,SAAA;AAAA,IACnC;AAAA,EACF;AAEA,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,SAAA,EAAW,IAAA,CAAK,cAAa,EAAG,SAAS,CAAA,EAAI,GAAG,IAAA,EAC5D,QAAA,EAAA;AAAA,IAAA,YAAA,uBACE,MAAA,EAAA,EAAK,EAAA,EAAI,iBAAiB,MAAA,EAAM,IAAA,EAAC,qBAElC,CAAA,GACE,IAAA;AAAA,oBACJ,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,OAAA;AAAA,QACL,SAAA,EAAW,aAAa,MAAM,CAAA;AAAA,QAC7B,GAAI,YAAA,IAAgB;AAAA,UACnB,IAAA,EAAM,QAAA;AAAA,UACN,QAAA,EAAU,CAAA;AAAA,UACV,iBAAA,EAAmB,kBAAA;AAAA,UACnB,YAAA,EAAc;AAAA,SAChB;AAAA,QAEC;AAAA;AAAA;AACH,GAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelHeader.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { makePrefixer } from '@salt-ds/core';
|
|
3
|
-
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
|
-
import { useWindow } from '@salt-ds/window';
|
|
5
|
-
import { clsx } from 'clsx';
|
|
6
|
-
import { forwardRef } from 'react';
|
|
7
|
-
import css_248z from './SidePanelHeader.css.js';
|
|
8
|
-
|
|
9
|
-
const withBaseName = makePrefixer("saltSidePanelHeader");
|
|
10
|
-
const SidePanelHeader = forwardRef(
|
|
11
|
-
function SidePanelHeader2(props, ref) {
|
|
12
|
-
const { children, className, ...rest } = props;
|
|
13
|
-
const targetWindow = useWindow();
|
|
14
|
-
useComponentCssInjection({
|
|
15
|
-
testId: "salt-side-panel-header",
|
|
16
|
-
css: css_248z,
|
|
17
|
-
window: targetWindow
|
|
18
|
-
});
|
|
19
|
-
return /* @__PURE__ */ jsx("div", { ref, className: clsx(withBaseName(), className), ...rest, children });
|
|
20
|
-
}
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
export { SidePanelHeader };
|
|
24
|
-
//# sourceMappingURL=SidePanelHeader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelHeader.js","sources":["../src/side-panel/SidePanelHeader.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentPropsWithRef, forwardRef } from \"react\";\nimport sidePanelHeaderCss from \"./SidePanelHeader.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelHeader\");\n\nexport interface SidePanelHeaderProps extends ComponentPropsWithRef<\"div\"> {}\n\nexport const SidePanelHeader = forwardRef<HTMLDivElement, SidePanelHeaderProps>(\n function SidePanelHeader(props, ref) {\n const { children, className, ...rest } = props;\n\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel-header\",\n css: sidePanelHeaderCss,\n window: targetWindow,\n });\n\n return (\n <div ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {children}\n </div>\n );\n },\n);\n"],"names":["SidePanelHeader","sidePanelHeaderCss"],"mappings":";;;;;;;;AAOA,MAAM,YAAA,GAAe,aAAa,qBAAqB,CAAA;AAIhD,MAAM,eAAA,GAAkB,UAAA;AAAA,EAC7B,SAASA,gBAAAA,CAAgB,KAAA,EAAO,GAAA,EAAK;AACnC,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,GAAG,MAAK,GAAI,KAAA;AAEzC,IAAA,MAAM,eAAe,SAAA,EAAU;AAE/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,wBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA,EAAI,GAAG,IAAA,EAC5D,QAAA,EACH,CAAA;AAAA,EAEJ;AACF;;;;"}
|