@hitachivantara/uikit-react-pentaho 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,11 +2,15 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const Tab = require("@mui/base/Tab");
4
4
  const uikitReactCore = require("@hitachivantara/uikit-react-core");
5
- const ICON_WIDTH = 32;
5
+ const ToolbarTabEditor = require("./ToolbarTabEditor.cjs");
6
6
  const MIN_TAB_WIDTH = 120;
7
7
  const MAX_TAB_WIDTH = 220;
8
+ const DROPDOWN_MENU_WIDTH = 64;
8
9
  const TAB_HEIGHT = 32;
9
- const TAB_LABEL_HEIGHT = 24;
10
+ const CLOSE_ICON_SIZE = 32;
11
+ const TAB_ICON_SIZE = 16;
12
+ const TAB_PADDING = uikitReactCore.theme.space.xs;
13
+ const TAB_COLOR = uikitReactCore.theme.palette.blue[50];
10
14
  const { staticClasses, useClasses } = uikitReactCore.createClasses(
11
15
  "HvCanvasToolbarTabs",
12
16
  {
@@ -18,85 +22,77 @@ const { staticClasses, useClasses } = uikitReactCore.createClasses(
18
22
  backgroundColor: uikitReactCore.theme.colors.atmo1,
19
23
  boxShadow: uikitReactCore.theme.colors.shadow,
20
24
  borderRadius: `0px 0px ${uikitReactCore.theme.radii.base} ${uikitReactCore.theme.radii.base}`,
21
- gap: uikitReactCore.theme.space.sm,
22
25
  transition: "width 0.3s ease"
23
26
  },
24
27
  tabsContainer: {
25
- position: "relative",
26
28
  display: "flex"
27
29
  },
28
30
  tabsList: {
29
31
  height: TAB_HEIGHT,
30
- background: uikitReactCore.theme.colors.atmo1
32
+ background: uikitReactCore.theme.colors.atmo1,
33
+ borderEndStartRadius: uikitReactCore.theme.radii.base
31
34
  },
32
35
  tab: {
33
- width: `clamp(${MIN_TAB_WIDTH}px, 100%, ${MAX_TAB_WIDTH}px)`,
36
+ boxSizing: "border-box",
34
37
  border: `1px solid ${uikitReactCore.theme.colors.atmo1}`,
35
38
  borderBottom: "none",
36
39
  borderRadius: "10px 10px 0 0",
37
40
  boxShadow: "none",
38
41
  backgroundColor: uikitReactCore.theme.colors.atmo1,
42
+ "&:first-of-type": { borderEndStartRadius: uikitReactCore.theme.radii.base },
39
43
  [`&.${Tab.tabClasses.selected}`]: {
40
44
  color: uikitReactCore.theme.colors.primary,
41
- backgroundColor: uikitReactCore.theme.colors.containerBackgroundHover,
45
+ backgroundColor: TAB_COLOR,
42
46
  borderColor: uikitReactCore.theme.colors.atmo4
47
+ },
48
+ [`&:hover:not(.${Tab.tabClasses.selected}), &:focus:not(.${Tab.tabClasses.selected})`]: {
49
+ borderRadius: 0,
50
+ backgroundColor: TAB_COLOR,
51
+ borderColor: TAB_COLOR,
52
+ "&:first-of-type": { borderEndStartRadius: uikitReactCore.theme.radii.base }
53
+ },
54
+ // Hide icon when editor is hovered and focused
55
+ [`&:has($tabLabelEditor:hover) $tabIconContainer, &:has(.${ToolbarTabEditor.toolbarTabEditorClasses.edit}) $tabIconContainer`]: {
56
+ display: "none"
57
+ },
58
+ // Hide close when editor is focused
59
+ [`&:has(.${ToolbarTabEditor.toolbarTabEditorClasses.edit}) $closeIconContainer`]: {
60
+ display: "none"
61
+ }
62
+ },
63
+ tabLabel: {
64
+ "&:not($tabLabelEditor)": {
65
+ margin: uikitReactCore.theme.spacing(0, "xs")
43
66
  }
44
67
  },
68
+ tabLabelEditor: {
69
+ color: uikitReactCore.theme.colors.primary
70
+ },
45
71
  tabContent: {
72
+ position: "relative",
46
73
  height: TAB_HEIGHT,
47
74
  display: "flex",
48
- justifyContent: "space-between",
49
- position: "relative",
75
+ justifyContent: "flex-start",
76
+ alignItems: "center",
50
77
  width: "100%",
51
- padding: uikitReactCore.theme.space.xs,
52
- "& > div:first-of-type:not($tabIcon)": {
53
- visibility: "hidden"
54
- },
55
- "& > div:nth-of-type(2)": {
56
- visibility: "hidden",
57
- minWidth: `calc(${MIN_TAB_WIDTH}px - ${uikitReactCore.theme.space.xs} - 2 * ${ICON_WIDTH}px)`,
58
- maxWidth: `calc(${MAX_TAB_WIDTH}px - ${uikitReactCore.theme.space.xs} - 2 * ${ICON_WIDTH}px)`
59
- },
60
- "& > div:nth-of-type(3)": {
61
- visibility: "hidden",
62
- marginRight: `calc(-1 * ${uikitReactCore.theme.space.xs})`
63
- }
78
+ padding: TAB_PADDING
64
79
  },
65
- tabIcon: {
80
+ tabIconContainer: {
66
81
  display: "flex",
67
82
  justifyContent: "center",
68
- alignItems: "center"
69
- },
70
- closeButton: {
71
- position: "absolute",
72
- top: 0,
73
- right: "calc(100% - var(--right))",
74
- color: "var(--close-color)"
75
- },
76
- tabLabel: {
77
- position: "absolute",
78
- width: "var(--editor-width)",
79
- right: `calc(100% - var(--right) + ${ICON_WIDTH}px)`,
80
- height: TAB_LABEL_HEIGHT,
81
- top: 4.5,
82
- "&:not($activeTabLabel)": {
83
- ...uikitReactCore.theme.typography.body,
84
- color: uikitReactCore.theme.colors.secondary_60,
85
- background: "none",
86
- cursor: "pointer"
87
- }
83
+ alignItems: "center",
84
+ width: TAB_ICON_SIZE
88
85
  },
89
- activeTabLabel: {
90
- "& button": {
91
- height: TAB_LABEL_HEIGHT,
92
- minHeight: TAB_LABEL_HEIGHT,
93
- backgroundColor: "transparent",
94
- "& p": { ...uikitReactCore.theme.typography.label, color: uikitReactCore.theme.colors.primary },
95
- "& span": { display: "none" }
96
- },
97
- [`&& .${uikitReactCore.baseInputClasses.inputRoot}`]: {
98
- height: TAB_LABEL_HEIGHT,
99
- minHeight: TAB_LABEL_HEIGHT
86
+ closeIconContainer: {
87
+ display: "flex",
88
+ justifyContent: "center",
89
+ alignItems: "center",
90
+ marginLeft: "auto",
91
+ marginRight: uikitReactCore.theme.spacing(-1),
92
+ width: CLOSE_ICON_SIZE,
93
+ "&:hover": {
94
+ backgroundColor: uikitReactCore.theme.colors.containerBackgroundHover,
95
+ borderRadius: uikitReactCore.theme.radii.circle
100
96
  }
101
97
  },
102
98
  tabDivider: {
@@ -112,12 +108,18 @@ const { staticClasses, useClasses } = uikitReactCore.createClasses(
112
108
  alignItems: "center",
113
109
  gap: uikitReactCore.theme.space.sm
114
110
  },
115
- dropdownMenu: {
116
- margin: uikitReactCore.theme.spacing(0, "sm")
111
+ dropdownMenuContainer: {
112
+ width: DROPDOWN_MENU_WIDTH,
113
+ display: "flex",
114
+ justifyContent: "center"
115
+ },
116
+ dropdownMenuListRoot: {
117
+ maxHeight: 220
117
118
  }
118
119
  }
119
120
  );
120
- exports.ICON_WIDTH = ICON_WIDTH;
121
+ exports.DROPDOWN_MENU_WIDTH = DROPDOWN_MENU_WIDTH;
122
+ exports.MAX_TAB_WIDTH = MAX_TAB_WIDTH;
121
123
  exports.MIN_TAB_WIDTH = MIN_TAB_WIDTH;
122
124
  exports.staticClasses = staticClasses;
123
125
  exports.useClasses = useClasses;
@@ -94,7 +94,6 @@ const HvCanvasBottomPanel = forwardRef((props, ref) => {
94
94
  id: `${id}-${tab.id}`,
95
95
  value: tab.id,
96
96
  className: classes.tab,
97
- tabIndex: 0,
98
97
  children: /* @__PURE__ */ jsx("div", { className: classes.tabTitle, children: typeof tab.title === "function" ? tab.title(overflowing) : tab.title })
99
98
  },
100
99
  tab.id
@@ -1 +1 @@
1
- {"version":3,"file":"BottomPanel.js","sources":["../../../../src/Canvas/BottomPanel/BottomPanel.tsx"],"sourcesContent":["import { forwardRef, useMemo } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport {\n ExtractNames,\n HvActionGeneric,\n HvActionsGeneric,\n HvActionsGenericProps,\n HvBaseProps,\n HvPanel,\n theme,\n useControlled,\n useDefaultProps,\n useUniqueId,\n} from \"@hitachivantara/uikit-react-core\";\n\nimport { HvCanvasPanelTab } from \"../PanelTab\";\nimport { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from \"../PanelTabs\";\nimport { staticClasses, useClasses } from \"./BottomPanel.styles\";\n\nexport { staticClasses as canvasBottomPanelClasses };\n\nexport type HvCanvasBottomPanelClasses = ExtractNames<typeof useClasses>;\n\nexport interface HvCanvasBottomPanelProps extends HvBaseProps {\n /** Open state of the bottom panel. */\n open?: boolean;\n /** Minimize state of the bottom panel tabs'. */\n minimize?: boolean;\n /** List of tabs visible on the panel. */\n tabs: {\n id: string | number;\n title: React.ReactNode | ((overflowing: boolean) => React.ReactNode);\n }[];\n /** Id of the selected tab if it needs to be controlled. */\n selectedTabId?: string | number;\n /** Callback triggered when a tab changes/is clicked. */\n onTabChange?: (\n event: React.SyntheticEvent | null,\n tabId: string | number | null,\n ) => void;\n /**\n * Actions to be rendered in the left side of a tab.\n * If more than one action is provided, a dropdown menu will be used.\n * These actions are not shown when the tab content is overflowing.\n */\n leftActions?: HvActionsGenericProps[\"actions\"];\n /**\n * Actions to be rendered in the right side of a tab.\n * If more than two actions are provided, a dropdown menu will be used to display the remaining actions.\n * These actions are not shown when the tab content is overflowing.\n */\n rightActions?: HvActionsGenericProps[\"actions\"];\n /**\n * Actions to be rendered in the right side of a tab when the tab content is overflowing.\n * These actions will replace both `leftActions` and `rightActions`.\n */\n overflowActions?: HvActionsGenericProps[\"actions\"];\n /** Callback triggered when an action is clicked. */\n onAction?: (\n event: React.SyntheticEvent,\n action: HvActionGeneric,\n tabId: string | number,\n ) => void;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvCanvasBottomPanelClasses;\n}\n\n/**\n * A bottom panel component to use in a canvas context.\n */\nexport const HvCanvasBottomPanel = forwardRef<\n HTMLDivElement,\n HvCanvasBottomPanelProps\n>((props, ref) => {\n const {\n id: idProp,\n className,\n children,\n open,\n tabs,\n minimize,\n leftActions,\n rightActions,\n overflowActions,\n selectedTabId: selectedTabIdProp,\n classes: classesProp,\n onTabChange,\n onAction,\n ...others\n } = useDefaultProps(\"HvCanvasBottomPanel\", props);\n\n const { classes, cx } = useClasses(classesProp);\n\n const id = useUniqueId(idProp);\n\n // Tab resize detector: to position tab actions and set the panel top right border radius\n const { width: tabWidth = 0, ref: tabRef } = useResizeDetector({\n handleHeight: false,\n });\n // Tab panel resize detector: to set the panel top right border radius\n const { width: panelWidth = 0, ref: panelRef } = useResizeDetector({\n handleHeight: false,\n });\n\n // Left actions resize detector: to position tab title according with actions\n const { width: leftActionWidth = 32, ref: leftActionRef } = useResizeDetector(\n {\n handleHeight: false,\n refreshMode: \"debounce\",\n refreshOptions: {\n trailing: true,\n },\n },\n );\n // Right actions resize detector: to position tab title according with actions\n const { width: rightActionWidth = 32, ref: rightActionRef } =\n useResizeDetector({\n handleHeight: false,\n refreshMode: \"debounce\",\n refreshOptions: {\n trailing: true,\n },\n });\n\n const overflowing = useMemo(() => {\n const availableWidth =\n tabWidth -\n (leftActions ? leftActionWidth : 0) -\n (rightActions ? rightActionWidth : 0);\n\n return availableWidth < 60;\n }, [leftActionWidth, leftActions, rightActionWidth, rightActions, tabWidth]);\n\n const [selectedTab, setSelectedTab] = useControlled<string | number | null>(\n selectedTabIdProp,\n tabs[0].id,\n );\n\n const handleTabChange: HvCanvasPanelTabsProps[\"onChange\"] = (\n event,\n tabId,\n ) => {\n setSelectedTab(tabId);\n onTabChange?.(event, tabId);\n };\n\n return (\n <div\n id={id}\n ref={ref}\n className={cx(\n classes.root,\n {\n [classes.closed]: !open,\n [classes.minimized]: minimize,\n [classes.multipleTabs]: tabs.length > 1,\n [classes.overflowing]: overflowing,\n },\n className,\n )}\n {...others}\n >\n <div className={classes.tabsRoot}>\n <HvCanvasPanelTabs\n style={{\n // @ts-ignore\n \"--left-actions-width\":\n overflowing || !leftActions\n ? theme.space.sm\n : `calc(${leftActionWidth}px + ${theme.space.xs})`,\n \"--right-actions-width\":\n !rightActions || (overflowing && !overflowActions)\n ? theme.space.sm\n : `calc(${overflowing ? 32 : rightActionWidth}px + ${theme.space.xs})`,\n }}\n onChange={handleTabChange}\n value={selectedTab}\n >\n {tabs.map((tab, index) => (\n <HvCanvasPanelTab\n ref={index === 0 ? tabRef : undefined}\n key={tab.id}\n id={`${id}-${tab.id}`}\n value={tab.id}\n className={classes.tab}\n tabIndex={0}\n >\n <div className={classes.tabTitle}>\n {typeof tab.title === \"function\"\n ? tab.title(overflowing)\n : tab.title}\n </div>\n </HvCanvasPanelTab>\n ))}\n </HvCanvasPanelTabs>\n {/* For accessibility purposes, these buttons cannot be children of a tablist so they are rendered as HvCanvasTabs sibling. */}\n {leftActions || rightActions || overflowActions\n ? tabs.map((tab, index) => {\n const btnsDisabled = selectedTab !== tab.id && !minimize;\n return (\n <div\n key={tab.id}\n style={{\n // @ts-ignore\n \"--tab-width\": `${tabWidth}px`,\n \"--right\": `calc((${index} + 1) * var(--tab-width))`,\n \"--left\": `calc(${index} * var(--tab-width))`,\n }}\n >\n {leftActions && !overflowing && (\n <div\n ref={leftActionRef}\n className={cx(classes.leftActions, {\n [classes.actionsDisabled]: btnsDisabled,\n })}\n >\n <HvActionsGeneric\n maxVisibleActions={1}\n actions={leftActions}\n disabled={btnsDisabled}\n onAction={(event, action) =>\n onAction?.(event, action, tab.id)\n }\n variant=\"secondaryGhost\"\n iconOnly\n />\n </div>\n )}\n {rightActions && !overflowing && (\n <div\n ref={rightActionRef}\n className={cx(classes.rightActions, {\n [classes.actionsDisabled]: btnsDisabled,\n })}\n >\n <HvActionsGeneric\n maxVisibleActions={2}\n actions={rightActions}\n disabled={btnsDisabled}\n onAction={(event, action) =>\n onAction?.(event, action, tab.id)\n }\n variant=\"secondaryGhost\"\n iconOnly\n />\n </div>\n )}\n {overflowActions && overflowing && (\n <div\n className={cx(classes.rightActions, {\n [classes.actionsDisabled]: btnsDisabled,\n })}\n >\n <HvActionsGeneric\n maxVisibleActions={0}\n actions={overflowActions}\n disabled={btnsDisabled}\n onAction={(event, action) =>\n onAction?.(event, action, tab.id)\n }\n variant=\"secondaryGhost\"\n iconOnly\n />\n </div>\n )}\n </div>\n );\n })\n : null}\n </div>\n <HvPanel\n ref={panelRef}\n role=\"tabpanel\"\n aria-labelledby={`${id}-${selectedTab}`}\n className={classes.content}\n style={{\n // @ts-ignore\n \"--right-border-radius\":\n tabWidth * tabs.length >= panelWidth ? \"0px\" : \"16px\",\n }}\n >\n {children}\n </HvPanel>\n </div>\n );\n});\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BottomPanel.js","sources":["../../../../src/Canvas/BottomPanel/BottomPanel.tsx"],"sourcesContent":["import { forwardRef, useMemo } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport {\n ExtractNames,\n HvActionGeneric,\n HvActionsGeneric,\n HvActionsGenericProps,\n HvBaseProps,\n HvPanel,\n theme,\n useControlled,\n useDefaultProps,\n useUniqueId,\n} from \"@hitachivantara/uikit-react-core\";\n\nimport { HvCanvasPanelTab } from \"../PanelTab\";\nimport { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from \"../PanelTabs\";\nimport { staticClasses, useClasses } from \"./BottomPanel.styles\";\n\nexport { staticClasses as canvasBottomPanelClasses };\n\nexport type HvCanvasBottomPanelClasses = ExtractNames<typeof useClasses>;\n\nexport interface HvCanvasBottomPanelProps extends HvBaseProps {\n /** Open state of the bottom panel. */\n open?: boolean;\n /** Minimize state of the bottom panel tabs'. */\n minimize?: boolean;\n /** List of tabs visible on the panel. */\n tabs: {\n id: string | number;\n title: React.ReactNode | ((overflowing: boolean) => React.ReactNode);\n }[];\n /** Id of the selected tab if it needs to be controlled. */\n selectedTabId?: string | number;\n /** Callback triggered when a tab changes/is clicked. */\n onTabChange?: (\n event: React.SyntheticEvent | null,\n tabId: string | number | null,\n ) => void;\n /**\n * Actions to be rendered in the left side of a tab.\n * If more than one action is provided, a dropdown menu will be used.\n * These actions are not shown when the tab content is overflowing.\n */\n leftActions?: HvActionsGenericProps[\"actions\"];\n /**\n * Actions to be rendered in the right side of a tab.\n * If more than two actions are provided, a dropdown menu will be used to display the remaining actions.\n * These actions are not shown when the tab content is overflowing.\n */\n rightActions?: HvActionsGenericProps[\"actions\"];\n /**\n * Actions to be rendered in the right side of a tab when the tab content is overflowing.\n * These actions will replace both `leftActions` and `rightActions`.\n */\n overflowActions?: HvActionsGenericProps[\"actions\"];\n /** Callback triggered when an action is clicked. */\n onAction?: (\n event: React.SyntheticEvent,\n action: HvActionGeneric,\n tabId: string | number,\n ) => void;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvCanvasBottomPanelClasses;\n}\n\n/**\n * A bottom panel component to use in a canvas context.\n */\nexport const HvCanvasBottomPanel = forwardRef<\n HTMLDivElement,\n HvCanvasBottomPanelProps\n>((props, ref) => {\n const {\n id: idProp,\n className,\n children,\n open,\n tabs,\n minimize,\n leftActions,\n rightActions,\n overflowActions,\n selectedTabId: selectedTabIdProp,\n classes: classesProp,\n onTabChange,\n onAction,\n ...others\n } = useDefaultProps(\"HvCanvasBottomPanel\", props);\n\n const { classes, cx } = useClasses(classesProp);\n\n const id = useUniqueId(idProp);\n\n // Tab resize detector: to position tab actions and set the panel top right border radius\n const { width: tabWidth = 0, ref: tabRef } = useResizeDetector({\n handleHeight: false,\n });\n // Tab panel resize detector: to set the panel top right border radius\n const { width: panelWidth = 0, ref: panelRef } = useResizeDetector({\n handleHeight: false,\n });\n\n // Left actions resize detector: to position tab title according with actions\n const { width: leftActionWidth = 32, ref: leftActionRef } = useResizeDetector(\n {\n handleHeight: false,\n refreshMode: \"debounce\",\n refreshOptions: {\n trailing: true,\n },\n },\n );\n // Right actions resize detector: to position tab title according with actions\n const { width: rightActionWidth = 32, ref: rightActionRef } =\n useResizeDetector({\n handleHeight: false,\n refreshMode: \"debounce\",\n refreshOptions: {\n trailing: true,\n },\n });\n\n const overflowing = useMemo(() => {\n const availableWidth =\n tabWidth -\n (leftActions ? leftActionWidth : 0) -\n (rightActions ? rightActionWidth : 0);\n\n return availableWidth < 60;\n }, [leftActionWidth, leftActions, rightActionWidth, rightActions, tabWidth]);\n\n const [selectedTab, setSelectedTab] = useControlled<string | number | null>(\n selectedTabIdProp,\n tabs[0].id,\n );\n\n const handleTabChange: HvCanvasPanelTabsProps[\"onChange\"] = (\n event,\n tabId,\n ) => {\n setSelectedTab(tabId);\n onTabChange?.(event, tabId);\n };\n\n return (\n <div\n id={id}\n ref={ref}\n className={cx(\n classes.root,\n {\n [classes.closed]: !open,\n [classes.minimized]: minimize,\n [classes.multipleTabs]: tabs.length > 1,\n [classes.overflowing]: overflowing,\n },\n className,\n )}\n {...others}\n >\n <div className={classes.tabsRoot}>\n <HvCanvasPanelTabs\n style={{\n // @ts-ignore\n \"--left-actions-width\":\n overflowing || !leftActions\n ? theme.space.sm\n : `calc(${leftActionWidth}px + ${theme.space.xs})`,\n \"--right-actions-width\":\n !rightActions || (overflowing && !overflowActions)\n ? theme.space.sm\n : `calc(${overflowing ? 32 : rightActionWidth}px + ${theme.space.xs})`,\n }}\n onChange={handleTabChange}\n value={selectedTab}\n >\n {tabs.map((tab, index) => (\n <HvCanvasPanelTab\n ref={index === 0 ? tabRef : undefined}\n key={tab.id}\n id={`${id}-${tab.id}`}\n value={tab.id}\n className={classes.tab}\n >\n <div className={classes.tabTitle}>\n {typeof tab.title === \"function\"\n ? tab.title(overflowing)\n : tab.title}\n </div>\n </HvCanvasPanelTab>\n ))}\n </HvCanvasPanelTabs>\n {/* For accessibility purposes, these buttons cannot be children of a tablist so they are rendered as HvCanvasTabs sibling. */}\n {leftActions || rightActions || overflowActions\n ? tabs.map((tab, index) => {\n const btnsDisabled = selectedTab !== tab.id && !minimize;\n return (\n <div\n key={tab.id}\n style={{\n // @ts-ignore\n \"--tab-width\": `${tabWidth}px`,\n \"--right\": `calc((${index} + 1) * var(--tab-width))`,\n \"--left\": `calc(${index} * var(--tab-width))`,\n }}\n >\n {leftActions && !overflowing && (\n <div\n ref={leftActionRef}\n className={cx(classes.leftActions, {\n [classes.actionsDisabled]: btnsDisabled,\n })}\n >\n <HvActionsGeneric\n maxVisibleActions={1}\n actions={leftActions}\n disabled={btnsDisabled}\n onAction={(event, action) =>\n onAction?.(event, action, tab.id)\n }\n variant=\"secondaryGhost\"\n iconOnly\n />\n </div>\n )}\n {rightActions && !overflowing && (\n <div\n ref={rightActionRef}\n className={cx(classes.rightActions, {\n [classes.actionsDisabled]: btnsDisabled,\n })}\n >\n <HvActionsGeneric\n maxVisibleActions={2}\n actions={rightActions}\n disabled={btnsDisabled}\n onAction={(event, action) =>\n onAction?.(event, action, tab.id)\n }\n variant=\"secondaryGhost\"\n iconOnly\n />\n </div>\n )}\n {overflowActions && overflowing && (\n <div\n className={cx(classes.rightActions, {\n [classes.actionsDisabled]: btnsDisabled,\n })}\n >\n <HvActionsGeneric\n maxVisibleActions={0}\n actions={overflowActions}\n disabled={btnsDisabled}\n onAction={(event, action) =>\n onAction?.(event, action, tab.id)\n }\n variant=\"secondaryGhost\"\n iconOnly\n />\n </div>\n )}\n </div>\n );\n })\n : null}\n </div>\n <HvPanel\n ref={panelRef}\n role=\"tabpanel\"\n aria-labelledby={`${id}-${selectedTab}`}\n className={classes.content}\n style={{\n // @ts-ignore\n \"--right-border-radius\":\n tabWidth * tabs.length >= panelWidth ? \"0px\" : \"16px\",\n }}\n >\n {children}\n </HvPanel>\n </div>\n );\n});\n"],"names":[],"mappings":"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"}
@@ -64,7 +64,6 @@ const HvCanvasSidePanel = forwardRef((props, ref) => {
64
64
  {
65
65
  id: `${id}-${tab.id}`,
66
66
  value: tab.id,
67
- tabIndex: 0,
68
67
  children: tab.content
69
68
  },
70
69
  tab.id
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanel.js","sources":["../../../../src/Canvas/SidePanel/SidePanel.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport {\n ExtractNames,\n HvBaseProps,\n HvIconButton,\n HvPanel,\n useControlled,\n useDefaultProps,\n useLabels,\n useUniqueId,\n} from \"@hitachivantara/uikit-react-core\";\nimport { End } from \"@hitachivantara/uikit-react-icons\";\n\nimport { HvCanvasPanelTab } from \"../PanelTab\";\nimport { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from \"../PanelTabs\";\nimport { staticClasses, useClasses } from \"./SidePanel.styles\";\n\nexport { staticClasses as canvasSidePanelClasses };\n\nexport type HvCanvasSidePanelClasses = ExtractNames<typeof useClasses>;\n\nconst DEFAULT_LABELS = {\n open: \"Open\",\n close: \"Close\",\n};\n\nexport interface HvCanvasSidePanelProps\n extends HvBaseProps<HTMLDivElement, \"onToggle\"> {\n /** When controlled, defines id the panel is open or not. */\n open?: boolean;\n /** When uncontrolled, defines the initial state of the panel. */\n defaultOpen?: boolean;\n /** List of tabs visible on the panel. */\n tabs?: {\n id: string | number;\n content: React.ReactNode;\n }[];\n /** Id of the selected tab if it needs to be controlled. */\n tab?: string | number;\n /** Callback triggered whenever the panel toggles. */\n onToggle?: (\n event: React.MouseEvent | React.KeyboardEvent,\n open: boolean,\n ) => void;\n /** Callback triggered when a tab changes/is clicked. */\n onTabChange?: (\n event: React.SyntheticEvent | null,\n tabId: string | number | null,\n ) => void;\n /** An object containing all the labels. */\n labels?: Partial<typeof DEFAULT_LABELS>;\n /** The content that will be rendered within the canvas panel. */\n children?: React.ReactNode;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvCanvasSidePanelClasses;\n}\n\n/**\n * A side panel component to use in a canvas context.\n */\nexport const HvCanvasSidePanel = forwardRef<\n HTMLDivElement,\n HvCanvasSidePanelProps\n>((props, ref) => {\n const {\n id: idProp,\n tab: tabProp,\n open: openProp,\n defaultOpen = false,\n tabs,\n onToggle,\n onTabChange,\n labels: labelsProp,\n className,\n children,\n classes: classesProp,\n ...others\n } = useDefaultProps(\"HvCanvasSidePanel\", props);\n\n const id = useUniqueId(idProp);\n\n const { classes, cx } = useClasses(classesProp);\n\n const labels = useLabels(DEFAULT_LABELS, labelsProp);\n\n const [open, setOpen] = useControlled(openProp, Boolean(defaultOpen));\n const [selectedTab, setSelectedTab] = useControlled<string | number | null>(\n tabProp,\n tabs?.[0]?.id ?? \"none\",\n );\n\n const handleTogglePanel = (event: React.MouseEvent | React.KeyboardEvent) => {\n setOpen((prev) => !prev);\n onToggle?.(event, !open);\n };\n\n const handleTabChange: HvCanvasPanelTabsProps[\"onChange\"] = (\n event,\n tabId,\n ) => {\n setSelectedTab(tabId);\n onTabChange?.(event, tabId);\n };\n\n return (\n <>\n <div\n ref={ref}\n id={id}\n className={cx(classes.root, className, {\n [classes.open]: open,\n [classes.close]: !open,\n })}\n {...others}\n >\n {tabs && (\n <HvCanvasPanelTabs\n className={classes.tabs}\n value={selectedTab}\n onChange={handleTabChange}\n >\n {tabs.map((tab) => (\n <HvCanvasPanelTab\n key={tab.id}\n id={`${id}-${tab.id}`}\n value={tab.id}\n tabIndex={0}\n >\n {tab.content}\n </HvCanvasPanelTab>\n ))}\n </HvCanvasPanelTabs>\n )}\n <HvPanel\n role={tabs ? \"tabpanel\" : undefined}\n aria-labelledby={tabs ? `${id}-${selectedTab}` : undefined}\n className={classes.content}\n >\n {children}\n </HvPanel>\n </div>\n <HvIconButton\n variant=\"primaryGhost\"\n title={open ? labels.close : labels.open}\n onClick={handleTogglePanel}\n className={cx(classes.handle, {\n [classes.handleOpen]: open,\n [classes.handleClose]: !open,\n })}\n >\n <End style={{ rotate: open ? \"180deg\" : undefined }} />\n </HvIconButton>\n </>\n );\n});\n"],"names":[],"mappings":";;;;;;;;AAqBA,MAAM,iBAAiB;AAAA,EACrB,MAAM;AAAA,EACN,OAAO;AACT;AAoCO,MAAM,oBAAoB,WAG/B,CAAC,OAAO,QAAQ;AACV,QAAA;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,GAAG;AAAA,EAAA,IACD,gBAAgB,qBAAqB,KAAK;AAExC,QAAA,KAAK,YAAY,MAAM;AAE7B,QAAM,EAAE,SAAS,GAAG,IAAI,WAAW,WAAW;AAExC,QAAA,SAAS,UAAU,gBAAgB,UAAU;AAE7C,QAAA,CAAC,MAAM,OAAO,IAAI,cAAc,UAAU,QAAQ,WAAW,CAAC;AAC9D,QAAA,CAAC,aAAa,cAAc,IAAI;AAAA,IACpC;AAAA,IACA,OAAO,CAAC,GAAG,MAAM;AAAA,EAAA;AAGb,QAAA,oBAAoB,CAAC,UAAkD;AACnE,YAAA,CAAC,SAAS,CAAC,IAAI;AACZ,eAAA,OAAO,CAAC,IAAI;AAAA,EAAA;AAGnB,QAAA,kBAAsD,CAC1D,OACA,UACG;AACH,mBAAe,KAAK;AACpB,kBAAc,OAAO,KAAK;AAAA,EAAA;AAG5B,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAW,GAAG,QAAQ,MAAM,WAAW;AAAA,UACrC,CAAC,QAAQ,IAAI,GAAG;AAAA,UAChB,CAAC,QAAQ,KAAK,GAAG,CAAC;AAAA,QAAA,CACnB;AAAA,QACA,GAAG;AAAA,QAEH,UAAA;AAAA,UACC,QAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,QAAQ;AAAA,cACnB,OAAO;AAAA,cACP,UAAU;AAAA,cAET,UAAA,KAAK,IAAI,CAAC,QACT;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE;AAAA,kBACnB,OAAO,IAAI;AAAA,kBACX,UAAU;AAAA,kBAET,UAAI,IAAA;AAAA,gBAAA;AAAA,gBALA,IAAI;AAAA,cAAA,CAOZ;AAAA,YAAA;AAAA,UACH;AAAA,UAEF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,OAAO,aAAa;AAAA,cAC1B,mBAAiB,OAAO,GAAG,EAAE,IAAI,WAAW,KAAK;AAAA,cACjD,WAAW,QAAQ;AAAA,cAElB;AAAA,YAAA;AAAA,UACH;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAO,OAAO,OAAO,QAAQ,OAAO;AAAA,QACpC,SAAS;AAAA,QACT,WAAW,GAAG,QAAQ,QAAQ;AAAA,UAC5B,CAAC,QAAQ,UAAU,GAAG;AAAA,UACtB,CAAC,QAAQ,WAAW,GAAG,CAAC;AAAA,QAAA,CACzB;AAAA,QAED,UAAA,oBAAC,OAAI,OAAO,EAAE,QAAQ,OAAO,WAAW,UAAa;AAAA,MAAA;AAAA,IACvD;AAAA,EACF,EAAA,CAAA;AAEJ,CAAC;"}
1
+ {"version":3,"file":"SidePanel.js","sources":["../../../../src/Canvas/SidePanel/SidePanel.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport {\n ExtractNames,\n HvBaseProps,\n HvIconButton,\n HvPanel,\n useControlled,\n useDefaultProps,\n useLabels,\n useUniqueId,\n} from \"@hitachivantara/uikit-react-core\";\nimport { End } from \"@hitachivantara/uikit-react-icons\";\n\nimport { HvCanvasPanelTab } from \"../PanelTab\";\nimport { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from \"../PanelTabs\";\nimport { staticClasses, useClasses } from \"./SidePanel.styles\";\n\nexport { staticClasses as canvasSidePanelClasses };\n\nexport type HvCanvasSidePanelClasses = ExtractNames<typeof useClasses>;\n\nconst DEFAULT_LABELS = {\n open: \"Open\",\n close: \"Close\",\n};\n\nexport interface HvCanvasSidePanelProps\n extends HvBaseProps<HTMLDivElement, \"onToggle\"> {\n /** When controlled, defines id the panel is open or not. */\n open?: boolean;\n /** When uncontrolled, defines the initial state of the panel. */\n defaultOpen?: boolean;\n /** List of tabs visible on the panel. */\n tabs?: {\n id: string | number;\n content: React.ReactNode;\n }[];\n /** Id of the selected tab if it needs to be controlled. */\n tab?: string | number;\n /** Callback triggered whenever the panel toggles. */\n onToggle?: (\n event: React.MouseEvent | React.KeyboardEvent,\n open: boolean,\n ) => void;\n /** Callback triggered when a tab changes/is clicked. */\n onTabChange?: (\n event: React.SyntheticEvent | null,\n tabId: string | number | null,\n ) => void;\n /** An object containing all the labels. */\n labels?: Partial<typeof DEFAULT_LABELS>;\n /** The content that will be rendered within the canvas panel. */\n children?: React.ReactNode;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: HvCanvasSidePanelClasses;\n}\n\n/**\n * A side panel component to use in a canvas context.\n */\nexport const HvCanvasSidePanel = forwardRef<\n HTMLDivElement,\n HvCanvasSidePanelProps\n>((props, ref) => {\n const {\n id: idProp,\n tab: tabProp,\n open: openProp,\n defaultOpen = false,\n tabs,\n onToggle,\n onTabChange,\n labels: labelsProp,\n className,\n children,\n classes: classesProp,\n ...others\n } = useDefaultProps(\"HvCanvasSidePanel\", props);\n\n const id = useUniqueId(idProp);\n\n const { classes, cx } = useClasses(classesProp);\n\n const labels = useLabels(DEFAULT_LABELS, labelsProp);\n\n const [open, setOpen] = useControlled(openProp, Boolean(defaultOpen));\n const [selectedTab, setSelectedTab] = useControlled<string | number | null>(\n tabProp,\n tabs?.[0]?.id ?? \"none\",\n );\n\n const handleTogglePanel = (event: React.MouseEvent | React.KeyboardEvent) => {\n setOpen((prev) => !prev);\n onToggle?.(event, !open);\n };\n\n const handleTabChange: HvCanvasPanelTabsProps[\"onChange\"] = (\n event,\n tabId,\n ) => {\n setSelectedTab(tabId);\n onTabChange?.(event, tabId);\n };\n\n return (\n <>\n <div\n ref={ref}\n id={id}\n className={cx(classes.root, className, {\n [classes.open]: open,\n [classes.close]: !open,\n })}\n {...others}\n >\n {tabs && (\n <HvCanvasPanelTabs\n className={classes.tabs}\n value={selectedTab}\n onChange={handleTabChange}\n >\n {tabs.map((tab) => (\n <HvCanvasPanelTab\n key={tab.id}\n id={`${id}-${tab.id}`}\n value={tab.id}\n >\n {tab.content}\n </HvCanvasPanelTab>\n ))}\n </HvCanvasPanelTabs>\n )}\n <HvPanel\n role={tabs ? \"tabpanel\" : undefined}\n aria-labelledby={tabs ? `${id}-${selectedTab}` : undefined}\n className={classes.content}\n >\n {children}\n </HvPanel>\n </div>\n <HvIconButton\n variant=\"primaryGhost\"\n title={open ? labels.close : labels.open}\n onClick={handleTogglePanel}\n className={cx(classes.handle, {\n [classes.handleOpen]: open,\n [classes.handleClose]: !open,\n })}\n >\n <End style={{ rotate: open ? \"180deg\" : undefined }} />\n </HvIconButton>\n </>\n );\n});\n"],"names":[],"mappings":";;;;;;;;AAqBA,MAAM,iBAAiB;AAAA,EACrB,MAAM;AAAA,EACN,OAAO;AACT;AAoCO,MAAM,oBAAoB,WAG/B,CAAC,OAAO,QAAQ;AACV,QAAA;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,GAAG;AAAA,EAAA,IACD,gBAAgB,qBAAqB,KAAK;AAExC,QAAA,KAAK,YAAY,MAAM;AAE7B,QAAM,EAAE,SAAS,GAAG,IAAI,WAAW,WAAW;AAExC,QAAA,SAAS,UAAU,gBAAgB,UAAU;AAE7C,QAAA,CAAC,MAAM,OAAO,IAAI,cAAc,UAAU,QAAQ,WAAW,CAAC;AAC9D,QAAA,CAAC,aAAa,cAAc,IAAI;AAAA,IACpC;AAAA,IACA,OAAO,CAAC,GAAG,MAAM;AAAA,EAAA;AAGb,QAAA,oBAAoB,CAAC,UAAkD;AACnE,YAAA,CAAC,SAAS,CAAC,IAAI;AACZ,eAAA,OAAO,CAAC,IAAI;AAAA,EAAA;AAGnB,QAAA,kBAAsD,CAC1D,OACA,UACG;AACH,mBAAe,KAAK;AACpB,kBAAc,OAAO,KAAK;AAAA,EAAA;AAG5B,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAW,GAAG,QAAQ,MAAM,WAAW;AAAA,UACrC,CAAC,QAAQ,IAAI,GAAG;AAAA,UAChB,CAAC,QAAQ,KAAK,GAAG,CAAC;AAAA,QAAA,CACnB;AAAA,QACA,GAAG;AAAA,QAEH,UAAA;AAAA,UACC,QAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,QAAQ;AAAA,cACnB,OAAO;AAAA,cACP,UAAU;AAAA,cAET,UAAA,KAAK,IAAI,CAAC,QACT;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE;AAAA,kBACnB,OAAO,IAAI;AAAA,kBAEV,UAAI,IAAA;AAAA,gBAAA;AAAA,gBAJA,IAAI;AAAA,cAAA,CAMZ;AAAA,YAAA;AAAA,UACH;AAAA,UAEF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,OAAO,aAAa;AAAA,cAC1B,mBAAiB,OAAO,GAAG,EAAE,IAAI,WAAW,KAAK;AAAA,cACjD,WAAW,QAAQ;AAAA,cAElB;AAAA,YAAA;AAAA,UACH;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAO,OAAO,OAAO,QAAQ,OAAO;AAAA,QACpC,SAAS;AAAA,QACT,WAAW,GAAG,QAAQ,QAAQ;AAAA,UAC5B,CAAC,QAAQ,UAAU,GAAG;AAAA,UACtB,CAAC,QAAQ,WAAW,GAAG,CAAC;AAAA,QAAA,CACzB;AAAA,QAED,UAAA,oBAAC,OAAI,OAAO,EAAE,QAAQ,OAAO,WAAW,UAAa;AAAA,MAAA;AAAA,IACvD;AAAA,EACF,EAAA,CAAA;AAEJ,CAAC;"}
@@ -1,4 +1,5 @@
1
- import { createClasses, theme } from "@hitachivantara/uikit-react-core";
1
+ import { theme, createClasses } from "@hitachivantara/uikit-react-core";
2
+ const boxShadow = `4px 0px 8px -4px ${theme.alpha("base_dark", "12%")}`;
2
3
  const { staticClasses, useClasses } = createClasses(
3
4
  "HvCanvasSidePanel",
4
5
  {
@@ -7,7 +8,7 @@ const { staticClasses, useClasses } = createClasses(
7
8
  position: "absolute",
8
9
  top: 0,
9
10
  left: 0,
10
- boxShadow: "4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)",
11
+ boxShadow,
11
12
  backgroundColor: "transparent",
12
13
  transition: "visibility 0.3s ease, width 0.3s ease",
13
14
  overflow: "hidden",
@@ -29,7 +30,7 @@ const { staticClasses, useClasses } = createClasses(
29
30
  width: "35px",
30
31
  display: "flex",
31
32
  justifyContent: "center",
32
- boxShadow: "4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)",
33
+ boxShadow,
33
34
  backgroundColor: theme.colors.atmo1,
34
35
  borderRadius: "0px 16px 16px 0px",
35
36
  position: "absolute",
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanel.styles.js","sources":["../../../../src/Canvas/SidePanel/SidePanel.styles.tsx"],"sourcesContent":["import { createClasses, theme } from \"@hitachivantara/uikit-react-core\";\n\nexport const { staticClasses, useClasses } = createClasses(\n \"HvCanvasSidePanel\",\n {\n root: {\n height: \"100%\",\n position: \"absolute\",\n top: 0,\n left: 0,\n boxShadow:\n \"4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)\",\n backgroundColor: \"transparent\",\n transition: \"visibility 0.3s ease, width 0.3s ease\",\n overflow: \"hidden\",\n \"&$open\": {\n width: 320,\n visibility: \"visible\",\n },\n \"&$close\": {\n width: 0,\n visibility: \"hidden\",\n },\n },\n tabs: {},\n content: {\n height: \"100%\",\n },\n handle: {\n height: \"172px\",\n width: \"35px\",\n display: \"flex\",\n justifyContent: \"center\",\n boxShadow:\n \"4px 0px 8px -4px color-mix(in srgb, #414141 12%, transparent)\",\n backgroundColor: theme.colors.atmo1,\n borderRadius: \"0px 16px 16px 0px\",\n position: \"absolute\",\n transition: \"left 0.3s ease\",\n top: \"calc(50% - 86px)\",\n \"&$handleOpen\": {\n left: 320,\n },\n \"&$handleClose\": {\n left: 0,\n },\n },\n open: {},\n close: {},\n handleOpen: {},\n handleClose: {},\n },\n);\n"],"names":[],"mappings":";AAEa,MAAA,EAAE,eAAe,WAAA,IAAe;AAAA,EAC3C;AAAA,EACA;AAAA,IACE,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WACE;AAAA,MACF,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,UAAU;AAAA,QACR,OAAO;AAAA,QACP,YAAY;AAAA,MACd;AAAA,MACA,WAAW;AAAA,QACT,OAAO;AAAA,QACP,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM,CAAC;AAAA,IACP,SAAS;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,WACE;AAAA,MACF,iBAAiB,MAAM,OAAO;AAAA,MAC9B,cAAc;AAAA,MACd,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,gBAAgB;AAAA,QACd,MAAM;AAAA,MACR;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,MAAM,CAAC;AAAA,IACP,OAAO,CAAC;AAAA,IACR,YAAY,CAAC;AAAA,IACb,aAAa,CAAC;AAAA,EAChB;AACF;"}
1
+ {"version":3,"file":"SidePanel.styles.js","sources":["../../../../src/Canvas/SidePanel/SidePanel.styles.tsx"],"sourcesContent":["import { createClasses, theme } from \"@hitachivantara/uikit-react-core\";\n\nconst boxShadow = `4px 0px 8px -4px ${theme.alpha(\"base_dark\", \"12%\")}`;\n\nexport const { staticClasses, useClasses } = createClasses(\n \"HvCanvasSidePanel\",\n {\n root: {\n height: \"100%\",\n position: \"absolute\",\n top: 0,\n left: 0,\n boxShadow,\n backgroundColor: \"transparent\",\n transition: \"visibility 0.3s ease, width 0.3s ease\",\n overflow: \"hidden\",\n \"&$open\": {\n width: 320,\n visibility: \"visible\",\n },\n \"&$close\": {\n width: 0,\n visibility: \"hidden\",\n },\n },\n tabs: {},\n content: {\n height: \"100%\",\n },\n handle: {\n height: \"172px\",\n width: \"35px\",\n display: \"flex\",\n justifyContent: \"center\",\n boxShadow,\n backgroundColor: theme.colors.atmo1,\n borderRadius: \"0px 16px 16px 0px\",\n position: \"absolute\",\n transition: \"left 0.3s ease\",\n top: \"calc(50% - 86px)\",\n \"&$handleOpen\": {\n left: 320,\n },\n \"&$handleClose\": {\n left: 0,\n },\n },\n open: {},\n close: {},\n handleOpen: {},\n handleClose: {},\n },\n);\n"],"names":[],"mappings":";AAEA,MAAM,YAAY,oBAAoB,MAAM,MAAM,aAAa,KAAK,CAAC;AAExD,MAAA,EAAE,eAAe,WAAA,IAAe;AAAA,EAC3C;AAAA,EACA;AAAA,IACE,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,UAAU;AAAA,QACR,OAAO;AAAA,QACP,YAAY;AAAA,MACd;AAAA,MACA,WAAW;AAAA,QACT,OAAO;AAAA,QACP,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM,CAAC;AAAA,IACP,SAAS;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB;AAAA,MACA,iBAAiB,MAAM,OAAO;AAAA,MAC9B,cAAc;AAAA,MACd,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,gBAAgB;AAAA,QACd,MAAM;AAAA,MACR;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,MAAM,CAAC;AAAA,IACP,OAAO,CAAC;AAAA,IACR,YAAY,CAAC;AAAA,IACb,aAAa,CAAC;AAAA,EAChB;AACF;"}
@@ -0,0 +1,150 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useRef, useState, useLayoutEffect } from "react";
3
+ import { createClasses, theme, useControlled, HvTypography, isKey } from "@hitachivantara/uikit-react-core";
4
+ import { Edit } from "@hitachivantara/uikit-react-icons";
5
+ const { staticClasses, useClasses } = createClasses(
6
+ "HvCanvasToolbarTabs-editor",
7
+ {
8
+ root: {
9
+ position: "relative",
10
+ display: "flex",
11
+ width: "100%",
12
+ overflow: "hidden",
13
+ "&:has($label:hover:not($edit))": {
14
+ color: theme.colors.secondary_80,
15
+ "& $editIcon": { visibility: "visible" }
16
+ }
17
+ },
18
+ edit: {
19
+ color: theme.colors.secondary_80,
20
+ borderColor: "currentColor",
21
+ backgroundColor: theme.colors.atmo1,
22
+ cursor: "text"
23
+ },
24
+ label: {
25
+ width: "100%",
26
+ boxSizing: "border-box",
27
+ border: "1px solid transparent",
28
+ borderRadius: theme.radii.base,
29
+ padding: theme.spacing(0, "sm", 0, "xs"),
30
+ textAlign: "start",
31
+ whiteSpace: "nowrap",
32
+ overflow: "hidden",
33
+ outline: "none",
34
+ "&:not($edit)": {
35
+ textOverflow: "ellipsis"
36
+ },
37
+ "&:hover:not($edit)": {
38
+ color: theme.colors.secondary_80,
39
+ borderColor: theme.colors.containerBackgroundHover,
40
+ backgroundColor: theme.colors.containerBackgroundHover
41
+ }
42
+ },
43
+ editIcon: {
44
+ position: "absolute",
45
+ right: theme.spacing(0.5),
46
+ top: 4,
47
+ width: 16,
48
+ height: 16,
49
+ visibility: "hidden",
50
+ pointerEvents: "none"
51
+ }
52
+ }
53
+ );
54
+ const ToolbarTabEditor = ({
55
+ id,
56
+ className,
57
+ edit: editProp,
58
+ value: valueProp,
59
+ defaultValue: defaultValueProp = "",
60
+ classes: classesProp,
61
+ onInput: onInputProp,
62
+ onClick: onClickProp,
63
+ onBlur: onBlurProp,
64
+ onKeyDown: onKeyDownProp,
65
+ onChange: onChangeProp,
66
+ onEditChange: onEditChangeProp,
67
+ ...others
68
+ }) => {
69
+ const { cx, classes } = useClasses(classesProp);
70
+ const contentEditableRef = useRef(null);
71
+ const [value, setValue] = useControlled(valueProp, defaultValueProp);
72
+ const [cachedValue, setCachedValue] = useState(value);
73
+ const [isEditing, setIsEditing] = useControlled(editProp, false);
74
+ const moveCursorToEnd = () => {
75
+ if (!contentEditableRef.current) return;
76
+ const element = contentEditableRef.current;
77
+ const range = document.createRange();
78
+ const selection = window.getSelection();
79
+ range.selectNodeContents(element);
80
+ range.collapse(false);
81
+ selection?.removeAllRanges();
82
+ selection?.addRange(range);
83
+ element.scrollLeft = element.scrollWidth;
84
+ };
85
+ const scrollContentToStart = () => {
86
+ if (!contentEditableRef.current) return;
87
+ const element = contentEditableRef.current;
88
+ element.scrollLeft = 0;
89
+ };
90
+ const changeEdit = (edit) => {
91
+ setIsEditing(edit);
92
+ onEditChangeProp?.(edit);
93
+ };
94
+ useLayoutEffect(() => {
95
+ if (isEditing) moveCursorToEnd();
96
+ }, [isEditing, value]);
97
+ const handleInput = (event) => {
98
+ const newValue = event.target.innerText || "";
99
+ setValue(newValue);
100
+ onInputProp?.(event);
101
+ onChangeProp?.(event, newValue);
102
+ };
103
+ const handleClick = (event) => {
104
+ setCachedValue(value);
105
+ changeEdit(true);
106
+ onClickProp?.(event);
107
+ };
108
+ const handleBlur = (event) => {
109
+ changeEdit(false);
110
+ scrollContentToStart();
111
+ const newValue = value.trim() || cachedValue;
112
+ setValue(newValue);
113
+ onBlurProp?.(event, newValue);
114
+ };
115
+ const handleKeyDown = (event) => {
116
+ if (isKey(event, "Enter")) {
117
+ handleBlur(event);
118
+ } else if (isKey(event, "Esc")) {
119
+ changeEdit(false);
120
+ setValue(cachedValue);
121
+ onChangeProp?.(event, cachedValue);
122
+ }
123
+ onKeyDownProp?.(event);
124
+ };
125
+ return /* @__PURE__ */ jsxs("div", { id, className: cx(classes.root, className), children: [
126
+ /* @__PURE__ */ jsx(
127
+ HvTypography,
128
+ {
129
+ ref: contentEditableRef,
130
+ contentEditable: isEditing,
131
+ className: cx(classes.label, { [classes.edit]: isEditing }),
132
+ variant: "label",
133
+ component: "span",
134
+ onInput: handleInput,
135
+ onClick: handleClick,
136
+ onBlur: handleBlur,
137
+ onKeyDown: handleKeyDown,
138
+ dangerouslySetInnerHTML: {
139
+ __html: value
140
+ },
141
+ ...others
142
+ }
143
+ ),
144
+ /* @__PURE__ */ jsx(Edit, { className: classes.editIcon, iconSize: "XS" })
145
+ ] });
146
+ };
147
+ export {
148
+ ToolbarTabEditor,
149
+ staticClasses as toolbarTabEditorClasses
150
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolbarTabEditor.js","sources":["../../../../src/Canvas/ToolbarTabs/ToolbarTabEditor.tsx"],"sourcesContent":["import { useLayoutEffect, useRef, useState } from \"react\";\nimport {\n createClasses,\n ExtractNames,\n HvTypography,\n HvTypographyProps,\n isKey,\n theme,\n useControlled,\n} from \"@hitachivantara/uikit-react-core\";\nimport { Edit } from \"@hitachivantara/uikit-react-icons\";\n\n// TODO - Extract component in the future: when we have more specs and/or is used in other components\n\nconst { staticClasses, useClasses } = createClasses(\n \"HvCanvasToolbarTabs-editor\",\n {\n root: {\n position: \"relative\",\n display: \"flex\",\n width: \"100%\",\n overflow: \"hidden\",\n \"&:has($label:hover:not($edit))\": {\n color: theme.colors.secondary_80,\n \"& $editIcon\": { visibility: \"visible\" },\n },\n },\n edit: {\n color: theme.colors.secondary_80,\n borderColor: \"currentColor\",\n backgroundColor: theme.colors.atmo1,\n cursor: \"text\",\n },\n label: {\n width: \"100%\",\n boxSizing: \"border-box\",\n border: \"1px solid transparent\",\n borderRadius: theme.radii.base,\n padding: theme.spacing(0, \"sm\", 0, \"xs\"),\n textAlign: \"start\",\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n outline: \"none\",\n \"&:not($edit)\": {\n textOverflow: \"ellipsis\",\n },\n \"&:hover:not($edit)\": {\n color: theme.colors.secondary_80,\n borderColor: theme.colors.containerBackgroundHover,\n backgroundColor: theme.colors.containerBackgroundHover,\n },\n },\n editIcon: {\n position: \"absolute\",\n right: theme.spacing(0.5),\n top: 4,\n width: 16,\n height: 16,\n visibility: \"hidden\",\n pointerEvents: \"none\",\n },\n },\n);\n\nexport { staticClasses as toolbarTabEditorClasses };\n\ntype ToolbarTabEditorClasses = ExtractNames<typeof useClasses>;\n\ninterface ToolbarTabEditorProps\n extends Omit<HvTypographyProps, \"classes\" | \"onBlur\" | \"onChange\"> {\n /** The value of the component. When used, the component has to be controlled. */\n value?: string;\n /** The default value of the component. */\n defaultValue?: string;\n /** Whether the editor is in edit mode. When used, the prop has to be controlled. */\n edit?: boolean;\n /** A Jss Object used to override or extend the styles applied. */\n classes?: ToolbarTabEditorClasses;\n /** Called the field is blurred. */\n onBlur?: (\n event: React.FocusEvent<Element> | React.KeyboardEvent<Element>,\n value: string,\n ) => void;\n /** Called the value changes. */\n onChange?: (\n event: React.FormEvent<Element> | React.KeyboardEvent<Element>,\n value: string,\n ) => void;\n /** Called the `edit` prop changes. */\n onEditChange?: (value: boolean) => void;\n}\n\nexport const ToolbarTabEditor = ({\n id,\n className,\n edit: editProp,\n value: valueProp,\n defaultValue: defaultValueProp = \"\",\n classes: classesProp,\n onInput: onInputProp,\n onClick: onClickProp,\n onBlur: onBlurProp,\n onKeyDown: onKeyDownProp,\n onChange: onChangeProp,\n onEditChange: onEditChangeProp,\n ...others\n}: ToolbarTabEditorProps) => {\n const { cx, classes } = useClasses(classesProp);\n\n const contentEditableRef = useRef<HTMLSpanElement>(null);\n\n const [value, setValue] = useControlled(valueProp, defaultValueProp);\n const [cachedValue, setCachedValue] = useState(value);\n const [isEditing, setIsEditing] = useControlled(editProp, false);\n\n const moveCursorToEnd = () => {\n if (!contentEditableRef.current) return;\n const element = contentEditableRef.current;\n const range = document.createRange();\n const selection = window.getSelection();\n range.selectNodeContents(element);\n range.collapse(false);\n selection?.removeAllRanges();\n selection?.addRange(range);\n element.scrollLeft = element.scrollWidth;\n };\n\n const scrollContentToStart = () => {\n if (!contentEditableRef.current) return;\n const element = contentEditableRef.current;\n element.scrollLeft = 0;\n };\n\n const changeEdit = (edit: boolean) => {\n setIsEditing(edit);\n onEditChangeProp?.(edit);\n };\n\n // Update cursor when value updates: otherwise it goes to the start\n useLayoutEffect(() => {\n if (isEditing) moveCursorToEnd();\n }, [isEditing, value]);\n\n const handleInput: HvTypographyProps[\"onInput\"] = (event) => {\n const newValue = (event.target as any).innerText || \"\";\n setValue(newValue);\n onInputProp?.(event);\n onChangeProp?.(event, newValue);\n };\n\n const handleClick: HvTypographyProps[\"onClick\"] = (event) => {\n setCachedValue(value);\n changeEdit(true);\n onClickProp?.(event);\n };\n\n const handleBlur = (\n event: React.FocusEvent<Element> | React.KeyboardEvent<Element>,\n ) => {\n changeEdit(false);\n scrollContentToStart();\n\n // Never leave the field empty\n const newValue = value.trim() || cachedValue;\n setValue(newValue);\n\n onBlurProp?.(event, newValue);\n };\n\n const handleKeyDown: HvTypographyProps[\"onKeyDown\"] = (event) => {\n if (isKey(event, \"Enter\")) {\n // Blur field\n handleBlur(event);\n } else if (isKey(event, \"Esc\")) {\n changeEdit(false);\n\n // Cancel editing\n setValue(cachedValue);\n onChangeProp?.(event, cachedValue);\n }\n onKeyDownProp?.(event);\n };\n\n return (\n <div id={id} className={cx(classes.root, className)}>\n <HvTypography\n ref={contentEditableRef}\n contentEditable={isEditing}\n className={cx(classes.label, { [classes.edit]: isEditing })}\n variant=\"label\"\n component=\"span\"\n onInput={handleInput}\n onClick={handleClick}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n // Using children is unstable in React for contentEditable so the value is rendered through dangerouslySetInnerHTML\n dangerouslySetInnerHTML={{\n __html: value,\n }}\n {...others}\n />\n <Edit className={classes.editIcon} iconSize=\"XS\" />\n </div>\n );\n};\n"],"names":[],"mappings":";;;;AAcM,MAAA,EAAE,eAAe,WAAA,IAAe;AAAA,EACpC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,MACJ,UAAU;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU;AAAA,MACV,kCAAkC;AAAA,QAChC,OAAO,MAAM,OAAO;AAAA,QACpB,eAAe,EAAE,YAAY,UAAU;AAAA,MACzC;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,MAAM,OAAO;AAAA,MACpB,aAAa;AAAA,MACb,iBAAiB,MAAM,OAAO;AAAA,MAC9B,QAAQ;AAAA,IACV;AAAA,IACA,OAAO;AAAA,MACL,OAAO;AAAA,MACP,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,cAAc,MAAM,MAAM;AAAA,MAC1B,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI;AAAA,MACvC,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,SAAS;AAAA,MACT,gBAAgB;AAAA,QACd,cAAc;AAAA,MAChB;AAAA,MACA,sBAAsB;AAAA,QACpB,OAAO,MAAM,OAAO;AAAA,QACpB,aAAa,MAAM,OAAO;AAAA,QAC1B,iBAAiB,MAAM,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,UAAU;AAAA,MACV,OAAO,MAAM,QAAQ,GAAG;AAAA,MACxB,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AA8BO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,OAAO;AAAA,EACP,cAAc,mBAAmB;AAAA,EACjC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,cAAc;AAAA,EACd,GAAG;AACL,MAA6B;AAC3B,QAAM,EAAE,IAAI,QAAQ,IAAI,WAAW,WAAW;AAExC,QAAA,qBAAqB,OAAwB,IAAI;AAEvD,QAAM,CAAC,OAAO,QAAQ,IAAI,cAAc,WAAW,gBAAgB;AACnE,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,WAAW,YAAY,IAAI,cAAc,UAAU,KAAK;AAE/D,QAAM,kBAAkB,MAAM;AACxB,QAAA,CAAC,mBAAmB,QAAS;AACjC,UAAM,UAAU,mBAAmB;AAC7B,UAAA,QAAQ,SAAS;AACjB,UAAA,YAAY,OAAO;AACzB,UAAM,mBAAmB,OAAO;AAChC,UAAM,SAAS,KAAK;AACpB,eAAW,gBAAgB;AAC3B,eAAW,SAAS,KAAK;AACzB,YAAQ,aAAa,QAAQ;AAAA,EAAA;AAG/B,QAAM,uBAAuB,MAAM;AAC7B,QAAA,CAAC,mBAAmB,QAAS;AACjC,UAAM,UAAU,mBAAmB;AACnC,YAAQ,aAAa;AAAA,EAAA;AAGjB,QAAA,aAAa,CAAC,SAAkB;AACpC,iBAAa,IAAI;AACjB,uBAAmB,IAAI;AAAA,EAAA;AAIzB,kBAAgB,MAAM;AACpB,QAAI,UAA2B;EAAA,GAC9B,CAAC,WAAW,KAAK,CAAC;AAEf,QAAA,cAA4C,CAAC,UAAU;AACrD,UAAA,WAAY,MAAM,OAAe,aAAa;AACpD,aAAS,QAAQ;AACjB,kBAAc,KAAK;AACnB,mBAAe,OAAO,QAAQ;AAAA,EAAA;AAG1B,QAAA,cAA4C,CAAC,UAAU;AAC3D,mBAAe,KAAK;AACpB,eAAW,IAAI;AACf,kBAAc,KAAK;AAAA,EAAA;AAGf,QAAA,aAAa,CACjB,UACG;AACH,eAAW,KAAK;AACK;AAGf,UAAA,WAAW,MAAM,KAAA,KAAU;AACjC,aAAS,QAAQ;AAEjB,iBAAa,OAAO,QAAQ;AAAA,EAAA;AAGxB,QAAA,gBAAgD,CAAC,UAAU;AAC3D,QAAA,MAAM,OAAO,OAAO,GAAG;AAEzB,iBAAW,KAAK;AAAA,IACP,WAAA,MAAM,OAAO,KAAK,GAAG;AAC9B,iBAAW,KAAK;AAGhB,eAAS,WAAW;AACpB,qBAAe,OAAO,WAAW;AAAA,IACnC;AACA,oBAAgB,KAAK;AAAA,EAAA;AAIrB,SAAA,qBAAC,SAAI,IAAQ,WAAW,GAAG,QAAQ,MAAM,SAAS,GAChD,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,iBAAiB;AAAA,QACjB,WAAW,GAAG,QAAQ,OAAO,EAAE,CAAC,QAAQ,IAAI,GAAG,WAAW;AAAA,QAC1D,SAAQ;AAAA,QACR,WAAU;AAAA,QACV,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,WAAW;AAAA,QAEX,yBAAyB;AAAA,UACvB,QAAQ;AAAA,QACV;AAAA,QACC,GAAG;AAAA,MAAA;AAAA,IACN;AAAA,wBACC,MAAK,EAAA,WAAW,QAAQ,UAAU,UAAS,MAAK;AAAA,EACnD,EAAA,CAAA;AAEJ;"}