diff --git a/.gitignore b/.gitignore index 6ab372b4b8..e76683d1a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules/ -dist/ coverage/ # Logs diff --git a/dist/components/IconHelper.d.ts b/dist/components/IconHelper.d.ts new file mode 100644 index 0000000000..1150727e01 --- /dev/null +++ b/dist/components/IconHelper.d.ts @@ -0,0 +1,10 @@ +import { CSSProperties, ReactNode } from 'react'; +import { Position } from './tooltip/Tooltip.component'; +type IconHelpProps = { + tooltipMessage: ReactNode; + placement?: Position; + overlayStyle?: CSSProperties; +}; +export declare const IconHelp: ({ tooltipMessage, overlayStyle, placement, }: IconHelpProps) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=IconHelper.d.ts.map \ No newline at end of file diff --git a/dist/components/IconHelper.d.ts.map b/dist/components/IconHelper.d.ts.map new file mode 100644 index 0000000000..9d4522af95 --- /dev/null +++ b/dist/components/IconHelper.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"IconHelper.d.ts","sourceRoot":"","sources":["../../src/lib/components/IconHelper.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAW,MAAM,6BAA6B,CAAC;AAEhE,KAAK,aAAa,GAAG;IACnB,cAAc,EAAE,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,QAAQ,iDAIlB,aAAa,4CAQf,CAAC"} \ No newline at end of file diff --git a/dist/components/IconHelper.js b/dist/components/IconHelper.js new file mode 100644 index 0000000000..347bd9bfd7 --- /dev/null +++ b/dist/components/IconHelper.js @@ -0,0 +1,4 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { Icon } from './icon/Icon.component'; +import { Tooltip } from './tooltip/Tooltip.component'; +export const IconHelp = ({ tooltipMessage, overlayStyle, placement = 'right', }) => (_jsx(Tooltip, { overlay: tooltipMessage, placement: placement, overlayStyle: overlayStyle, children: _jsx(Icon, { name: "Info", color: "buttonSecondary" }) })); diff --git a/dist/components/UnsuccessfulResult.component.d.ts b/dist/components/UnsuccessfulResult.component.d.ts new file mode 100644 index 0000000000..a9d415f93d --- /dev/null +++ b/dist/components/UnsuccessfulResult.component.d.ts @@ -0,0 +1,28 @@ +import { TableHeightKeyType, TableLocalType } from './tablev2/TableUtils'; +export declare const NoResult: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, import("styled-system").LayoutProps>> & import("styled-system").FlexboxProps>> & import("styled-system").GridProps>> & import("styled-system").SpaceProps>, string | number | symbol> & import("styled-system").PositionProps>> & import("styled-system").ColorProps>, string | number | symbol> & import("styled-system").BackgroundProps>, import("csstype").Property.Background> & import("styled-system").BordersProps>> & import("styled-system").TypographyProps>> & import("styled-system").ShadowProps>> & { + gap?: string | number; +} & { + height: number | string; +}, never>; +export type UnsuccessfulResultProps = { + name?: { + en: { + singular: string; + plural: string; + }; + fr?: { + singular: string; + plural: string; + }; + }; + locale?: TableLocalType; + status: 'error' | 'loading' | 'idle' | 'noResult'; +} & ({ + rowHeight: TableHeightKeyType; + heightInRem?: never; +} | { + rowHeight?: never; + heightInRem?: number | string; +}); +export declare const UnsuccessfulResult: (props: UnsuccessfulResultProps) => import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=UnsuccessfulResult.component.d.ts.map \ No newline at end of file diff --git a/dist/components/UnsuccessfulResult.component.d.ts.map b/dist/components/UnsuccessfulResult.component.d.ts.map new file mode 100644 index 0000000000..cb38d827f9 --- /dev/null +++ b/dist/components/UnsuccessfulResult.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"UnsuccessfulResult.component.d.ts","sourceRoot":"","sources":["../../src/lib/components/UnsuccessfulResult.component.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAClB,cAAc,EAGf,MAAM,sBAAsB,CAAC;AAK9B,eAAO,MAAM,QAAQ;;;YAAyB,MAAM,GAAG,MAAM;SAO5D,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,CAAC,EAAE;QACL,EAAE,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QACzC,EAAE,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;IACF,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;CACnD,GAAG,CACA;IAAE,SAAS,EAAE,kBAAkB,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,GACtD;IAAE,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CACvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAAW,uBAAuB,4CAehE,CAAC"} \ No newline at end of file diff --git a/dist/components/UnsuccessfulResult.component.js b/dist/components/UnsuccessfulResult.component.js new file mode 100644 index 0000000000..7c9b533e67 --- /dev/null +++ b/dist/components/UnsuccessfulResult.component.js @@ -0,0 +1,21 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { Icon } from './icon/Icon.component'; +import { Loader } from './loader/Loader.component'; +import { tableRowHeight, translatedMessages, } from './tablev2/TableUtils'; +import { Text } from './text/Text.component'; +import { Box } from './box/Box'; +import { spacing } from '../spacing'; +export const NoResult = styled(Box) ` + display: flex; + justify-content: center; + align-items: center; + color: ${(props) => props.theme.textSecondary}; + height: ${(props) => props.height}rem; + gap: ${spacing.r8}; +`; +export const UnsuccessfulResult = (props) => { + const { heightInRem = 5, name, locale, status, rowHeight } = props; + const height = rowHeight ? tableRowHeight[rowHeight] : heightInRem; + return (_jsxs(NoResult, { height: height, children: [(status === 'loading' || status === 'idle') && _jsx(Loader, {}), status === 'error' && (_jsx(Icon, { name: "Exclamation-circle", color: "statusWarning" })), _jsx(Text, { color: "textSecondary", children: translatedMessages(status, name, locale) })] })); +}; diff --git a/dist/components/accordion/Accordion.component.d.ts b/dist/components/accordion/Accordion.component.d.ts new file mode 100644 index 0000000000..d1e9e1c8c7 --- /dev/null +++ b/dist/components/accordion/Accordion.component.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; +export type AccordionProps = { + title: string; + id: string; + children: React.ReactNode; + style?: React.CSSProperties; +}; +export declare const Accordion: ({ title, id, style, children }: AccordionProps) => import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=Accordion.component.d.ts.map \ No newline at end of file diff --git a/dist/components/accordion/Accordion.component.d.ts.map b/dist/components/accordion/Accordion.component.d.ts.map new file mode 100644 index 0000000000..fdbebfe374 --- /dev/null +++ b/dist/components/accordion/Accordion.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Accordion.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/accordion/Accordion.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAUxC,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAkCF,eAAO,MAAM,SAAS,mCAAoC,cAAc,4CAuDvE,CAAC"} \ No newline at end of file diff --git a/dist/components/accordion/Accordion.component.js b/dist/components/accordion/Accordion.component.js new file mode 100644 index 0000000000..53f953e40f --- /dev/null +++ b/dist/components/accordion/Accordion.component.js @@ -0,0 +1,52 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { useState } from 'react'; +import { spacing, Stack } from '../../spacing'; +import { Box } from '../box/Box'; +import { Icon } from '../icon/Icon.component'; +import styled from 'styled-components'; +import { Text } from '../text/Text.component'; +const AccordionContainer = styled(Box) ` + width: 100%; + height: auto; +`; +const AccordionHeader = styled.button ` + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border: none; + width: 100%; + cursor: pointer; + background-color: transparent; + color: ${(props) => props.theme.textPrimary}; + padding: 0; + font-family: 'Lato'; +`; +const AccordionContent = styled.div ` + overflow: hidden; + opacity: ${(props) => (props.isOpen ? 1 : 0)}; + transition: + height 0.3s ease-in, + opacity 0.3s ease-in, + visibility 0.3s; + visibility: ${(props) => (props.isOpen ? 'visible' : 'hidden')}; +`; +const Wrapper = styled.div ` + padding: ${spacing.r8} 0 ${spacing.r8} 0; +`; +export const Accordion = ({ title, id, style, children }) => { + const [isOpen, setIsOpen] = useState(false); + const handleToggleContent = (e) => { + setIsOpen((prev) => !prev); + }; + return (_jsxs(AccordionContainer, { children: [_jsx("h3", { style: { margin: 0 }, children: _jsx(AccordionHeader, { type: "button", id: `Accordion-header-${id}`, onClick: handleToggleContent, "aria-controls": id, "aria-expanded": isOpen, onKeyDown: (e) => (e.key === 'Enter' || e.key === ' ') && handleToggleContent, children: _jsxs(Stack, { direction: "horizontal", gap: "r8", children: [_jsx(Icon, { name: "Chevron-up", size: "lg", style: { + transform: isOpen ? 'rotate(0deg)' : 'rotate(180deg)', + transition: 'transform 0.3s ease-in', + } }), _jsx(Text, { isEmphazed: true, children: title })] }) }) }), _jsx(AccordionContent, { ref: (element) => { + if (isOpen) { + element === null || element === void 0 ? void 0 : element.style.setProperty('height', element.scrollHeight + 'px'); + } + else { + element === null || element === void 0 ? void 0 : element.style.setProperty('height', '0px'); + } + }, isOpen: isOpen, id: id, "aria-labelledby": `Accordion-header-${id}`, role: "region", children: _jsx(Wrapper, { style: style, children: children }) })] })); +}; diff --git a/dist/components/areachart/AreaChart.component.d.ts b/dist/components/areachart/AreaChart.component.d.ts new file mode 100644 index 0000000000..dbece182a5 --- /dev/null +++ b/dist/components/areachart/AreaChart.component.d.ts @@ -0,0 +1,13 @@ +type Props = { + id: string; + data: Array>; + xAxis: Record; + yAxis: Array>; + color?: Record; + areas: Array>; + width?: number; + height?: number; +}; +declare function AreaChart({ id, data, xAxis, yAxis, color, height, width, areas, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { AreaChart }; +//# sourceMappingURL=AreaChart.component.d.ts.map \ No newline at end of file diff --git a/dist/components/areachart/AreaChart.component.d.ts.map b/dist/components/areachart/AreaChart.component.d.ts.map new file mode 100644 index 0000000000..2d1f4f2842 --- /dev/null +++ b/dist/components/areachart/AreaChart.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AreaChart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/areachart/AreaChart.component.tsx"],"names":[],"mappings":"AAEA,KAAK,KAAK,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,iBAAS,SAAS,CAAC,EACjB,EAAE,EACF,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAY,EACZ,KAAY,EACZ,KAAU,EACV,GAAG,IAAI,EACR,EAAE,KAAK,2CAuBP;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/areachart/AreaChart.component.js b/dist/components/areachart/AreaChart.component.js new file mode 100644 index 0000000000..f8f2a19bb8 --- /dev/null +++ b/dist/components/areachart/AreaChart.component.js @@ -0,0 +1,27 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { VegaChart } from '../vegachart/VegaChart.component'; +function AreaChart({ id, data, xAxis, yAxis, color, height = 300, width = 1000, areas = [], ...rest }) { + const lines = yAxis.map((y) => ({ + mark: { + type: 'line', + }, + encoding: { + y, + }, + })); + const spec = { + data: { + values: data, + }, + encoding: { + x: xAxis, + color, + }, + layer: [...lines, ...areas], + height, + width, + ...rest, + }; + return _jsx(VegaChart, { className: "sc-areachart", id: id, spec: spec }); +} +export { AreaChart }; diff --git a/dist/components/banner/Banner.component.d.ts b/dist/components/banner/Banner.component.d.ts new file mode 100644 index 0000000000..5eba59dd2b --- /dev/null +++ b/dist/components/banner/Banner.component.d.ts @@ -0,0 +1,10 @@ +import { Variant } from '../constants'; +export type Props = { + icon?: React.ReactNode; + title?: string; + children: React.ReactNode; + variant: Variant; +}; +declare function Banner({ icon, title, children, variant, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Banner }; +//# sourceMappingURL=Banner.component.d.ts.map \ No newline at end of file diff --git a/dist/components/banner/Banner.component.d.ts.map b/dist/components/banner/Banner.component.d.ts.map new file mode 100644 index 0000000000..8da49f8622 --- /dev/null +++ b/dist/components/banner/Banner.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Banner.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/banner/Banner.component.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAmCF,iBAAS,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAUjE;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/banner/Banner.component.js b/dist/components/banner/Banner.component.js new file mode 100644 index 0000000000..362e60f487 --- /dev/null +++ b/dist/components/banner/Banner.component.js @@ -0,0 +1,40 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, fontWeight } from '../../style/theme'; +import { getThemeVariantSelector } from '../../utils'; +const BannerContainer = styled.div ` + ${(props) => css ` + color: ${props.theme.textPrimary}; + background-color: ${props.theme.backgroundLevel1}; + display: flex; + padding: ${spacing.r8}; + align-items: center; + font-size: ${fontSize.small}; + border: 1px solid; + border-left: 5px solid; + border-radius: 3px; + border-color: ${getThemeVariantSelector()}; + i { + display: flex; + align-items: center; + margin-left: ${spacing.r8}; + color: ${getThemeVariantSelector()}; + } + `} +`; +const TextContainer = styled.div ` + display: flex; + flex-direction: column; +`; +const Text = styled.span ` + margin-left: ${spacing.r16}; +`; +const Title = styled.div ` + margin-left: ${spacing.r16}; + font-weight: ${fontWeight.bold}; +`; +function Banner({ icon, title, children, variant, ...rest }) { + return (_jsxs(BannerContainer, { className: "sc-banner", variant: variant, children: [icon, _jsxs(TextContainer, { children: [title && _jsx(Title, { children: title }), _jsx(Text, { children: children })] })] })); +} +export { Banner }; diff --git a/dist/components/barchart/BarChart.component.d.ts b/dist/components/barchart/BarChart.component.d.ts new file mode 100644 index 0000000000..db9c4e870f --- /dev/null +++ b/dist/components/barchart/BarChart.component.d.ts @@ -0,0 +1,12 @@ +type Props = { + id: string; + data: Array>; + xAxis: Record; + yAxis: Record; + color?: Record; + height?: number; + barConfig?: Record; +}; +declare function BarChart({ id, data, xAxis, yAxis, color, height, barConfig, }: Props): import("react/jsx-runtime").JSX.Element; +export { BarChart }; +//# sourceMappingURL=BarChart.component.d.ts.map \ No newline at end of file diff --git a/dist/components/barchart/BarChart.component.d.ts.map b/dist/components/barchart/BarChart.component.d.ts.map new file mode 100644 index 0000000000..be96d358e1 --- /dev/null +++ b/dist/components/barchart/BarChart.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"BarChart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchart/BarChart.component.tsx"],"names":[],"mappings":"AACA,KAAK,KAAK,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC,CAAC;AAEF,iBAAS,QAAQ,CAAC,EAChB,EAAE,EACF,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAY,EACZ,SAAS,GACV,EAAE,KAAK,2CAwBP;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/barchart/BarChart.component.js b/dist/components/barchart/BarChart.component.js new file mode 100644 index 0000000000..cbedde8cdd --- /dev/null +++ b/dist/components/barchart/BarChart.component.js @@ -0,0 +1,22 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { VegaChart } from '../vegachartv2/VegaChartV2.component'; +function BarChart({ id, data, xAxis, yAxis, color, height = 200, barConfig, }) { + const spec = { + mark: { + type: 'bar', + ...barConfig, + }, + width: 'container', + height, + data: { + values: data, + }, + encoding: { + x: xAxis, + y: yAxis, + color, + }, + }; + return (_jsx(VegaChart, { id: id, spec: spec }, `barchart-${id}-${data.length}`)); +} +export { BarChart }; diff --git a/dist/components/box/Box.d.ts b/dist/components/box/Box.d.ts new file mode 100644 index 0000000000..c6bbe6a8e0 --- /dev/null +++ b/dist/components/box/Box.d.ts @@ -0,0 +1,7 @@ +import type { LayoutProps, FlexboxProps, ColorProps, SpaceProps, PositionProps, GridProps, BackgroundProps, BordersProps, TypographyProps, ShadowProps } from 'styled-system'; +export type BoxComponentProps = LayoutProps & FlexboxProps & GridProps & SpaceProps & PositionProps & ColorProps & BackgroundProps & BordersProps & TypographyProps & ShadowProps & { + gap?: string | number; +}; +declare const Box: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, BoxComponentProps, never>; +export { Box }; +//# sourceMappingURL=Box.d.ts.map \ No newline at end of file diff --git a/dist/components/box/Box.d.ts.map b/dist/components/box/Box.d.ts.map new file mode 100644 index 0000000000..b11bddf439 --- /dev/null +++ b/dist/components/box/Box.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Box.d.ts","sourceRoot":"","sources":["../../../src/lib/components/box/Box.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,eAAe,EACf,YAAY,EACZ,eAAe,EACf,WAAW,EACZ,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,iBAAiB,GAAG,WAAW,GACzC,YAAY,GACZ,SAAS,GACT,UAAU,GACV,aAAa,GACb,UAAU,GACV,eAAe,GACf,YAAY,GACZ,eAAe,GACf,WAAW,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAE1C,QAAA,MAAM,GAAG,wHAiBR,CAAC;AACF,OAAO,EAAE,GAAG,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/box/Box.js b/dist/components/box/Box.js new file mode 100644 index 0000000000..4b61cd6e37 --- /dev/null +++ b/dist/components/box/Box.js @@ -0,0 +1,21 @@ +import styled from 'styled-components'; +import { layout, flexbox, grid, space, position, color, background, border, typography, shadow, system, } from 'styled-system'; +const Box = styled.div ` + ${layout} + ${flexbox} + ${grid} + ${space} + ${position} + ${color} + ${background} + ${border} + ${typography} + ${shadow} + ${system({ + gap: { + property: 'gap', + scale: 'space', + }, +})} +`; +export { Box }; diff --git a/dist/components/breadcrumb/Breadcrumb.component.d.ts b/dist/components/breadcrumb/Breadcrumb.component.d.ts new file mode 100644 index 0000000000..dcc3af36a9 --- /dev/null +++ b/dist/components/breadcrumb/Breadcrumb.component.d.ts @@ -0,0 +1,6 @@ +type Props = { + paths: Array; +}; +declare const Breadcrumb: ({ paths, ...rest }: Props) => import("react/jsx-runtime").JSX.Element; +export { Breadcrumb }; +//# sourceMappingURL=Breadcrumb.component.d.ts.map \ No newline at end of file diff --git a/dist/components/breadcrumb/Breadcrumb.component.d.ts.map b/dist/components/breadcrumb/Breadcrumb.component.d.ts.map new file mode 100644 index 0000000000..e27fd293aa --- /dev/null +++ b/dist/components/breadcrumb/Breadcrumb.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Breadcrumb.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/breadcrumb/Breadcrumb.component.tsx"],"names":[],"mappings":"AAKA,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;CAC3B,CAAC;AAuEF,QAAA,MAAM,UAAU,uBAA6B,KAAK,4CAoBjD,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/breadcrumb/Breadcrumb.component.js b/dist/components/breadcrumb/Breadcrumb.component.js new file mode 100644 index 0000000000..d448ea7789 --- /dev/null +++ b/dist/components/breadcrumb/Breadcrumb.component.js @@ -0,0 +1,77 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { ellipsis } from 'polished'; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize } from '../../style/theme'; +import { Icon } from '../icon/Icon.component'; +const BreadcrumbContainer = styled.ol ` + display: flex; + list-style-type: none; + padding-left: 0; + margin: 0; + overflow-y: auto; +`; +const BreadcrumbItem = styled.li ` + box-sizing: border-box; + height: 100%; + font-size: ${fontSize.larger}; + ${ellipsis('250px')} + min-width: 3rem; + + ${(props) => { + const { textPrimary, selectedActive, textLink } = props.theme; + if (props.active) { + return css ` + * { + text-decoration: none; + color: ${textPrimary}; + } + color: ${textPrimary}; + `; + } + return css ` + * { + text-decoration: none; + color: ${textLink}; + } + color: ${textLink}; + border-bottom: 2px solid transparent; + &:hover { + * { + color: ${selectedActive}; + } + color: ${selectedActive}; + border-bottom: 2px solid ${selectedActive}; + } + `; +}} +`; +const BreadcrumbSeparator = styled.li ` + ${(props) => css ` + color: ${props.theme.textPrimary}; + padding: ${spacing.r4} ${spacing.r8}; + display: flex; + align-items: center; + font-size: ${fontSize.small}; + `} +`; +const withBreadcrumbSeparator = (lastIndex) => (acc, item, index) => { + const notLast = index < lastIndex; + return notLast + ? [ + ...acc, + item, + _jsx(BreadcrumbSeparator, { className: "sc-breadcrumb_separator", children: _jsx(Icon, { name: "Chevron-right" }) }, `sc-breadcrumb_separator_${index}`), + ] + : [...acc, item]; +}; +const Breadcrumb = ({ paths = [], ...rest }) => { + const lastIndex = paths.length - 1; + const breadcrumbItems = paths + .map((item, index) => { + return (_jsx(BreadcrumbItem, { className: "sc-breadcrumb_item", active: index === lastIndex, children: item }, `sc-breadcrumb_item_${index}`)); + }) + .reduce(withBreadcrumbSeparator(lastIndex), []); + return (_jsx(BreadcrumbContainer, { className: "sc-breadcrumb", ...rest, children: breadcrumbItems })); +}; +export { Breadcrumb }; diff --git a/dist/components/button/Button.component.d.ts b/dist/components/button/Button.component.d.ts new file mode 100644 index 0000000000..401189af28 --- /dev/null +++ b/dist/components/button/Button.component.d.ts @@ -0,0 +1,27 @@ +import { Size } from '../constants'; +type Props = { + text?: string; + size?: Size; + variant?: 'buttonPrimary' | 'buttonSecondary' | 'buttonDelete' | 'backgroundLevel1'; + outlined?: boolean; + inverted?: boolean; + disabled?: boolean; + icon?: JSX.Element; + href?: string; + title?: string; + type?: string; + isLoading?: boolean; + onClick?: (arg0: any) => void; +}; +export declare const ButtonStyled: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, {}, never>; +export declare const ButtonIcon: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>; +export declare const ButtonText: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>; +export declare const ButtonContent: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>; +/** + * @deprecated + * You should use ButtonV2 with + * import { Button } from '@scality/core-ui/dist/next'; + */ +declare function Button({ text, href, icon, size, variant, outlined, disabled, onClick, title, isLoading, type, inverted, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Button }; +//# sourceMappingURL=Button.component.d.ts.map \ No newline at end of file diff --git a/dist/components/button/Button.component.d.ts.map b/dist/components/button/Button.component.d.ts.map new file mode 100644 index 0000000000..205447d0af --- /dev/null +++ b/dist/components/button/Button.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Button.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/button/Button.component.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,KAAK,KAAK,GAAG;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IAIZ,OAAO,CAAC,EACJ,eAAe,GACf,iBAAiB,GACjB,cAAc,GACd,kBAAkB,CAAC;IAEvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/B,CAAC;AACF,eAAO,MAAM,YAAY,4GA+LxB,CAAC;AACF,eAAO,MAAM,UAAU,0GAStB,CAAC;AACF,eAAO,MAAM,UAAU,0GAItB,CAAC;AACF,eAAO,MAAM,aAAa,0GAEzB,CAAC;AAGF;;;;GAIG;AACH,iBAAS,MAAM,CAAC,EACd,IAAS,EACT,IAAS,EACT,IAAW,EACX,IAAa,EACb,OAAyB,EACzB,QAAgB,EAChB,QAAgB,EAChB,OAAO,EACP,KAAU,EACV,SAAiB,EACjB,IAAe,EACf,QAAgB,EAChB,GAAG,IAAI,EACR,EAAE,KAAK,2CAgDP;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/button/Button.component.js b/dist/components/button/Button.component.js new file mode 100644 index 0000000000..3d6acfa27b --- /dev/null +++ b/dist/components/button/Button.component.js @@ -0,0 +1,227 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +// @ts-nocheck +// Legacy Button should not be use anymore +import { lighten } from 'polished'; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, fontWeight, white } from '../../style/theme'; +import { Loader } from '../loader/Loader.component'; +export const ButtonStyled = styled.button ` + -webkit-appearance: none; + -moz-appearance: none; + position: relative; + display: inline-flex; + user-select: none; + vertical-align: middle; + align-items: center; + justify-content: center; + box-sizing: border-box; + text-decoration: none; + border: none; + text-decoration: none; + font-weight: ${fontWeight.base}; + + &:hover, + &:focus, + &:active { + outline: none; + cursor: pointer; + } + + ${(props) => { + switch (props.size) { + case 'smaller': + return css ` + padding: 7px 14px; + font-size: ${fontSize.smaller}; + border-radius: 4px; + height: 27px; + `; + case 'small': + return css ` + padding: 8px 16px; + font-size: ${fontSize.small}; + border-radius: 5px; + height: 30px; + `; + case 'large': + return css ` + padding: 10px 20px; + font-size: ${fontSize.large}; + border-radius: 7px; + height: 40px; + `; + case 'larger': + return css ` + padding: 11px 22px; + font-size: ${fontSize.larger}; + border-radius: 8px; + height: 48px; + `; + case 'base': + default: + return css ` + padding: 12px 16px; + font-size: ${fontSize.base}; + border-radius: 6px; + height: 32px; + `; + } +}} + + ${(props) => { + if (props.isLoading) { + return css ` + > span { + display: flex; + .sc-loader { + margin: 0px ${spacing.r4}; + svg { + fill: ${props.theme.textPrimary} !important; + } + } + } + `; + } + if (props.outlined) { + return css ` + border-width: 1px; + border-style: solid; + border-color: ${props.theme.buttonSecondary}; + // to be checked + background-color: ${props.theme.backgroundLevel1}; + color: ${props.theme.textPrimary}; + + &:hover { + border-color: ${props.theme.infoPrimary}; + color: ${props.theme.textPrimary}; + } + `; + } + else if (props.variant === 'buttonPrimary') { + return css ` + background-color: ${props.theme.buttonPrimary}; + border: 1px solid ${props.theme.buttonPrimary}; + color: ${props.theme.textPrimary}; + &:hover { + background-color: ${props.theme.highlight}; + outline: none; + border: 1px solid ${props.theme.infoPrimary}; + } + `; + } + else if (props.variant === 'buttonSecondary') { + return css ` + background-color: ${props.theme.buttonSecondary}; + border: 1px solid ${props.theme.buttonSecondary}; + color: ${props.theme.textPrimary}; + &:hover { + background-color: ${props.theme.infoPrimary}; + border: 1px solid ${props.theme.infoPrimary}; + } + `; + } + else if (props.variant === 'buttonDelete') { + return css ` + background-color: ${props.theme.buttonDelete}; + border: 1px solid ${props.theme.buttonDelete}; + color: ${props.theme.statusCritical}; + &:hover { + background-color: ${props.theme.statusCritical}; + border: 1px solid ${props.theme.infoPrimary}; + color: ${props.theme.textPrimary}; + } + `; + } + else if (props.variant === 'backgroundLevel1') { + return css ` + background-color: ${props.theme.backgroundLevel1}; + color: ${props.theme.textPrimary}; + &:hover { + background-color: ${props.theme.highlight}; + } + `; + } + else { + return css ` + background-color: ${props.theme.backgroundLevel1}; + border: 1px solid ${props.theme.backgroundLevel1}; + color: ${props.theme.statusCritical}; + &:hover { + background-color: ${props.theme.backgroundLevel1}; + border: 1px solid ${props.theme.infoPrimary}; + color: ${props.theme.textPrimary}; + } + `; + } +}} + +${(props) => { + const brandLighter = lighten(0.2, props.theme[props.variant]).toString(); + return css ` + ${props.disabled + ? ` + box-shadow: none; + pointer-events: none; + opacity: 0.3; + border-color: ${brandLighter}; + color: ${white}; + ` + : null} + `; +}} + +${(props) => { + const brandLighter = lighten(0.2, props.theme[props.variant]).toString(); + const brandLight = lighten(0.1, props.theme[props.variant]).toString(); + return css ` + ${!props.text && props.icon && props.inverted + ? ` + padding: 0; + height: auto; + border: none; + background-color: transparent; + color: ${props.disabled ? brandLight : props.theme[props.variant]}; + + &:hover{ + background-color: transparent; + color: ${brandLight}; + border: none; + } + + &:active { + background-color: transparent; + color: ${brandLighter}; + } + ` + : null} + `; +}} +`; +export const ButtonIcon = styled.span ` + ${(props) => props.text && + css ` + padding-right: 8px; + display: inline-flex; + justify-content: center; + align-items: center; + `} +`; +export const ButtonText = styled.span ` + display: inline-flex; + justify-content: center; + align-items: center; +`; +export const ButtonContent = styled.span ` + position: relative; +`; +const Anchor = ButtonStyled.withComponent('a'); +/** + * @deprecated + * You should use ButtonV2 with + * import { Button } from '@scality/core-ui/dist/next'; + */ +function Button({ text = '', href = '', icon = null, size = 'base', variant = 'buttonPrimary', outlined = false, disabled = false, onClick, title = '', isLoading = false, type = 'button', inverted = false, ...rest }) { + return href && href.length ? (_jsxs(Anchor, { className: "sc-button", href: href, variant: variant, outlined: outlined, disabled: disabled, size: size, title: title, ...rest, children: [icon && (_jsx(ButtonIcon, { text: text, size: size, children: icon })), _jsx(ButtonText, { children: text })] })) : (_jsx(ButtonStyled, { className: "sc-button", variant: variant, outlined: outlined, disabled: disabled || isLoading, size: size, onClick: onClick, title: title, isLoading: isLoading, type: type, inverted: inverted, icon: icon, text: text, ...rest, children: _jsxs(ButtonContent, { children: [isLoading && _jsx(Loader, { size: size }), _jsxs("span", { className: "sc-button-text", children: [icon && (_jsx(ButtonIcon, { text: text, size: size, children: icon })), _jsx(ButtonText, { children: text })] })] }) })); +} +export { Button }; diff --git a/dist/components/buttonv2/Buttonv2.component.d.ts b/dist/components/buttonv2/Buttonv2.component.d.ts new file mode 100644 index 0000000000..159520481f --- /dev/null +++ b/dist/components/buttonv2/Buttonv2.component.d.ts @@ -0,0 +1,26 @@ +import React, { ButtonHTMLAttributes } from 'react'; +import { Loader } from '../loader/Loader.component'; +import { Props as TooltipProps } from '../tooltip/Tooltip.component'; +export declare const FocusVisibleStyle: import("styled-components").FlattenInterpolation>; +export type Props = Omit, 'size' | 'label'> & { + variant?: 'primary' | 'secondary' | 'danger' | 'outline'; + size?: 'default' | 'inline'; + disabled?: boolean; + onClick?: (event: React.MouseEvent) => void; + icon?: React.ReactNode; + label?: React.ReactNode; + tooltip?: Omit; + isLoading?: boolean; +}; +export declare const ButtonStyled: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, Props, never>; +export declare const ButtonLabel: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>; +export declare const ButtonIcon: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, { + label: React.ReactNode; +}, never>; +export declare const ButtonLoader: import("styled-components").StyledComponent; +declare function Button({ variant, size, disabled, label, icon, onClick, tooltip, isLoading, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Button }; +//# sourceMappingURL=Buttonv2.component.d.ts.map \ No newline at end of file diff --git a/dist/components/buttonv2/Buttonv2.component.d.ts.map b/dist/components/buttonv2/Buttonv2.component.d.ts.map new file mode 100644 index 0000000000..c430d94e84 --- /dev/null +++ b/dist/components/buttonv2/Buttonv2.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Buttonv2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/buttonv2/Buttonv2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAIpD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAW,KAAK,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE9E,eAAO,MAAM,iBAAiB,oIAI7B,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,IAAI,CACtB,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,GAAG,OAAO,CACjB,GAAG;IACF,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzD,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AACF,eAAO,MAAM,YAAY,+GAqJxB,CAAC;AACF,eAAO,MAAM,WAAW,0GAIvB,CAAC;AACF,eAAO,MAAM,UAAU;WAAwB,KAAK,CAAC,SAAS;SAS7D,CAAC;AAEF,eAAO,MAAM,YAAY;;;SAaxB,CAAC;AAEF,iBAAS,MAAM,CAAC,EACd,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,OAAO,EACP,OAAO,EACP,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CAqDP;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/buttonv2/Buttonv2.component.js b/dist/components/buttonv2/Buttonv2.component.js new file mode 100644 index 0000000000..5e4404154b --- /dev/null +++ b/dist/components/buttonv2/Buttonv2.component.js @@ -0,0 +1,199 @@ +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, fontWeight } from '../../style/theme'; +import { Loader } from '../loader/Loader.component'; +import { Tooltip } from '../tooltip/Tooltip.component'; +export const FocusVisibleStyle = css ` + outline: dashed ${spacing.r2} ${(props) => props.theme.selectedActive}; + outline-offset: ${spacing.r2}; + z-index: 1000; +`; +export const ButtonStyled = styled.button ` + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + display: inline-flex; + user-select: none; + vertical-align: middle; + align-items: center; + justify-content: center; + box-sizing: border-box; + text-decoration: none; + border: none; + text-decoration: none; + font-family: 'Lato'; + font-weight: ${fontWeight.base}; + + padding: ${spacing.r4} ${spacing.r8}; + font-size: ${fontSize.base}; + border-radius: ${spacing.r4}; + height: ${(props) => (props.size === 'inline' ? spacing.r24 : spacing.r32)}; + ${(props) => { + const brand = props.theme; + switch (props.variant) { + case 'primary': + return css ` + background-color: ${brand.buttonPrimary}; + border: ${spacing.r1} solid ${brand.buttonPrimary}; + color: ${brand.textPrimary}; + &:hover:enabled { + cursor: pointer; + border: ${spacing.r1} solid ${brand.infoPrimary}; + color: ${brand.textPrimary}; + } + // :focus-visible is the keyboard-only version of :focus + &:focus-visible:enabled { + ${FocusVisibleStyle} + color: ${brand.textPrimary}; + } + &:active:enabled { + cursor: pointer; + color: ${brand.textPrimary}; + border: ${spacing.r1} solid ${brand.infoSecondary}; + } + `; + case 'secondary': + return css ` + background-color: ${brand.buttonSecondary}; + border: ${spacing.r1} solid ${brand.buttonSecondary}; + color: ${brand.textPrimary}; + &:hover:enabled { + cursor: pointer; + border: ${spacing.r1} solid ${brand.infoPrimary}; + color: ${brand.textPrimary}; + } + &:focus-visible:enabled { + ${FocusVisibleStyle} + color: ${brand.textPrimary}; + } + &:active:enabled { + cursor: pointer; + color: ${brand.textPrimary}; + border: ${spacing.r1} solid ${brand.buttonSecondary}; + } + `; + case 'danger': + return css ` + background-color: ${brand.buttonDelete}; + border: ${spacing.r1} solid ${brand.buttonDelete}; + color: ${brand.statusCritical}; + &:hover:enabled { + cursor: pointer; + border: ${spacing.r1} solid ${brand.infoPrimary}; + } + &:focus-visible:enabled { + ${FocusVisibleStyle} + } + &:active:enabled { + cursor: pointer; + border: ${spacing.r1} solid ${brand.infoSecondary}; + } + `; + case 'outline': + return css ` + border: ${spacing.r1} solid ${brand.buttonSecondary}; + background-color: transparent; + color: ${brand.textPrimary}; + &:hover:enabled { + cursor: pointer; + border-color: ${brand.infoPrimary}; + color: ${brand.textPrimary}; + } + &:focus-visible:enabled { + ${FocusVisibleStyle} + border-color: ${brand.buttonSecondary}; + } + &:active:enabled { + cursor: pointer; + border: ${spacing.r1} solid ${brand.infoSecondary}; + color: ${brand.textPrimary}; + } + `; + default: + } +}} + + ${(props) => { + return css ` + ${props.disabled + ? ` + cursor: not-allowed !important; + pointer-events: auto !important; + opacity: 0.5; + ` + : null} + `; +}} + + + ${(props) => { + const brand = props.theme; + return css ` + ${props.icon && !props.label && !props.variant + ? ` + background-color: transparent; + border: none; + color: ${brand.textSecondary}; + + &:hover{ + cursor: pointer; + border: none; + color: ${brand.textPrimary}; + } + &:focus-visible:enabled { + outline: dashed ${spacing.r2} ${brand.selectedActive}; + } + &:active { + cursor: pointer; + color: ${brand.textPrimary}; + } + ` + : null} + `; +}} +`; +export const ButtonLabel = styled.span ` + display: inline-flex; + justify-content: center; + align-items: center; +`; +export const ButtonIcon = styled.span ` + ${(props) => props.label && + css ` + padding-right: ${spacing.r8}; + display: inline-flex; + justify-content: center; + align-items: center; + `} +`; +export const ButtonLoader = styled(Loader) ` + ${(props) => { + return css ` + margin-right: ${props.label ? spacing.r8 : '0'}; + svg { + fill: ${props.variant === 'danger' + ? props.theme.statusCritical + : props.variant === 'outline' + ? props.theme.textPrimary + : props.theme.textSecondary}; + } + `; +}} +`; +function Button({ variant, size, disabled, label, icon, onClick, tooltip, isLoading, ...rest }) { + if (!icon && !label) { + console.warn('Please specify either icon or label prop for the button component.'); + } + if (!label && icon && !tooltip) { + console.warn('Please specify the tooltip for the standalone icon button.'); + } + return (_jsx(Tooltip, { placement: tooltip ? tooltip.placement : undefined, overlay: tooltip && tooltip.overlay, overlayStyle: tooltip && tooltip.overlayStyle, children: _jsx(ButtonStyled, { className: "sc-button", variant: variant, disabled: isLoading || disabled, label: label, icon: icon, onClick: onClick, size: size, ...rest, children: _jsxs(_Fragment, { children: [icon && + (isLoading ? (_jsx(ButtonLoader, { size: "small", variant: variant, label: label })) : (_jsx(ButtonIcon, { label: label, "aria-label": tooltip && + tooltip.overlay && + typeof tooltip.overlay === 'string' + ? tooltip.overlay + : undefined, children: icon }))), !icon && isLoading && (_jsx(ButtonLoader, { size: "small", variant: variant, label: label })), _jsx(ButtonLabel, { children: label })] }) }) })); +} +export { Button }; diff --git a/dist/components/buttonv2/CopyButton.component.d.ts b/dist/components/buttonv2/CopyButton.component.d.ts new file mode 100644 index 0000000000..b2d5197b2e --- /dev/null +++ b/dist/components/buttonv2/CopyButton.component.d.ts @@ -0,0 +1,14 @@ +import { Props } from './Buttonv2.component'; +export declare const COPY_STATE_IDLE = "idle"; +export declare const COPY_STATE_SUCCESS = "success"; +export declare const COPY_STATE_UNSUPPORTED = "unsupported"; +export declare const useClipboard: () => { + copy: (text: any) => void; + copyStatus: string; +}; +export declare const CopyButton: ({ label, textToCopy, variant, ...props }: { + label?: string; + textToCopy: string; + variant?: "outline" | "ghost"; +} & Props) => import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=CopyButton.component.d.ts.map \ No newline at end of file diff --git a/dist/components/buttonv2/CopyButton.component.d.ts.map b/dist/components/buttonv2/CopyButton.component.d.ts.map new file mode 100644 index 0000000000..06dfe19c80 --- /dev/null +++ b/dist/components/buttonv2/CopyButton.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"CopyButton.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/buttonv2/CopyButton.component.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAErD,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,YAAY;;;CAuBxB,CAAC;AAEF,eAAO,MAAM,UAAU,6CAKpB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAC/B,GAAG,KAAK,4CA+CR,CAAC"} \ No newline at end of file diff --git a/dist/components/buttonv2/CopyButton.component.js b/dist/components/buttonv2/CopyButton.component.js new file mode 100644 index 0000000000..e067392d60 --- /dev/null +++ b/dist/components/buttonv2/CopyButton.component.js @@ -0,0 +1,52 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { useEffect, useState } from 'react'; +import { Icon } from '../icon/Icon.component'; +import { Button } from './Buttonv2.component'; +export const COPY_STATE_IDLE = 'idle'; +export const COPY_STATE_SUCCESS = 'success'; +export const COPY_STATE_UNSUPPORTED = 'unsupported'; +export const useClipboard = () => { + const [copyStatus, setCopyStatus] = useState(COPY_STATE_IDLE); + useEffect(() => { + const timer = setTimeout(() => { + setCopyStatus(COPY_STATE_IDLE); + }, 2000); + return () => clearTimeout(timer); + }, [copyStatus]); + const copyToClipboard = (text) => { + if (!navigator || !navigator.clipboard) { + setCopyStatus(COPY_STATE_UNSUPPORTED); + return; + } + navigator.clipboard.writeText(text); + setCopyStatus(COPY_STATE_SUCCESS); + }; + return { + copy: copyToClipboard, + copyStatus: copyStatus, + }; +}; +export const CopyButton = ({ label, textToCopy, variant, ...props }) => { + const { copy, copyStatus } = useClipboard(); + return (_jsx(Button, { ...props, variant: variant === 'outline' ? 'outline' : undefined, style: { + minWidth: + //Just to make sure the width of the button stays the same when copied! + variant === 'outline' + ? (label ? label.length / 2 : 0) + 7 + 'rem' + : undefined, + }, label: variant === 'outline' + ? copyStatus === COPY_STATE_SUCCESS + ? `Copied${label ? ' ' + label + '' : ''}!` + : `Copy${label ? ' ' + label : ''}` + : undefined, icon: _jsx(Icon, { name: copyStatus === COPY_STATE_SUCCESS ? 'Check' : 'Copy', color: copyStatus === COPY_STATE_SUCCESS ? 'statusHealthy' : undefined }), disabled: copyStatus === COPY_STATE_SUCCESS || props.disabled, onClick: () => copy(textToCopy), type: "button", tooltip: variant !== 'outline' + ? { + overlay: copyStatus === COPY_STATE_SUCCESS + ? 'Copied !' + : `Copy${label ? ' ' + label : ''}`, + overlayStyle: { + maxWidth: '20rem', + }, + placement: 'top', + } + : undefined })); +}; diff --git a/dist/components/card/Card.component.d.ts b/dist/components/card/Card.component.d.ts new file mode 100644 index 0000000000..b5268cce3c --- /dev/null +++ b/dist/components/card/Card.component.d.ts @@ -0,0 +1,28 @@ +import { HTMLProps } from 'react'; +type CardElementProps = { + children: React.ReactNode; + className?: string; +}; +export declare const CardHeader: ({ children, className, ...rest }: CardElementProps) => import("react/jsx-runtime").JSX.Element; +export declare const CardBody: ({ children, className, ...rest }: CardElementProps) => import("react/jsx-runtime").JSX.Element; +export declare const CardBodyContainer: ({ children, className, ...rest }: CardElementProps) => import("react/jsx-runtime").JSX.Element; +type CardProps = { + width?: string; + height?: string; + headerBackgroundColor?: string; + bodyBackgroundColor?: string; + status?: 'healthy' | 'warning' | 'critical'; + onClick?: () => void; + active?: boolean; + disabled?: boolean; + children: React.ReactNode; + className?: string; +} & HTMLProps; +declare function Card({ width, height, headerBackgroundColor, bodyBackgroundColor, status, onClick, active, disabled, children, className, ...rest }: CardProps): import("react/jsx-runtime").JSX.Element; +declare namespace Card { + var Header: ({ children, className, ...rest }: CardElementProps) => import("react/jsx-runtime").JSX.Element; + var Body: ({ children, className, ...rest }: CardElementProps) => import("react/jsx-runtime").JSX.Element; + var BodyContainer: ({ children, className, ...rest }: CardElementProps) => import("react/jsx-runtime").JSX.Element; +} +export { Card }; +//# sourceMappingURL=Card.component.d.ts.map \ No newline at end of file diff --git a/dist/components/card/Card.component.d.ts.map b/dist/components/card/Card.component.d.ts.map new file mode 100644 index 0000000000..5e00ab4f76 --- /dev/null +++ b/dist/components/card/Card.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Card.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/card/Card.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMlC,KAAK,gBAAgB,GAAG;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAmDF,eAAO,MAAM,UAAU,qCAhDqB,gBAAgB,4CAgDC,CAAC;AAC9D,eAAO,MAAM,QAAQ,qCAjDuB,gBAAgB,4CAiDH,CAAC;AAC1D,eAAO,MAAM,iBAAiB,qCAlDc,gBAAgB,4CAkDe,CAAC;AAoD5E,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;AAC9B,iBAAS,IAAI,CAAC,EACZ,KAAc,EACd,MAAe,EACf,qBAAyC,EACzC,mBAAwC,EACxC,MAAa,EACb,OAAc,EACd,MAAc,EACd,QAAgB,EAChB,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,SAAS,2CA4CX;kBAxDQ,IAAI;mDAlH+B,gBAAgB;iDAAhB,gBAAgB;0DAAhB,gBAAgB;;AA8K5D,OAAO,EAAE,IAAI,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/card/Card.component.js b/dist/components/card/Card.component.js new file mode 100644 index 0000000000..6b4484a6f0 --- /dev/null +++ b/dist/components/card/Card.component.js @@ -0,0 +1,101 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { createContext } from 'react'; +import styled, { css } from 'styled-components'; +import { FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +import { hex2RGB } from '../../utils'; +const CardContext = createContext(null); +function withCompoundCheck(Component) { + return ({ children, className, ...rest }) => (_jsx(CardContext.Consumer, { children: (value) => { + const componentName = Component.displayName; + if (!value) { + throw new Error(`${componentName ? componentName : 'This component'} cannot be rendered outside the Card component`); + } + return (_jsx(Component, { className: [ + componentName ? `sc-${componentName.toLowerCase()}` : null, + className, + ].join(' '), ...rest, children: children })); + } })); +} +const StyledCardHeader = styled.div ` + padding: 0.7rem; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + font-weight: bold; +`; +StyledCardHeader.displayName = 'CardHeader'; +const StyledCardBody = styled.div ` + padding: 0.7rem 0; + color: ${(props) => props.theme.textPrimary}; +`; +StyledCardBody.displayName = 'CardBody'; +const StyledCardBodyContainer = styled.div ` + display: flex; + align-items: center; + justify-content: center; + flex: 1; +`; +StyledCardBodyContainer.displayName = 'CardBodyContainer'; +export const CardHeader = withCompoundCheck(StyledCardHeader); +export const CardBody = withCompoundCheck(StyledCardBody); +export const CardBodyContainer = withCompoundCheck(StyledCardBodyContainer); +const StyledCard = styled.div ` + border-radius: 3px; + display: flex; + flex-flow: column; + width: ${(props) => props.width}; + height: ${(props) => props.height}; + background: ${(props) => props.theme[props.bodyBackgroundColor]}; + filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.2)); + ${StyledCardBody} { + opacity: ${(props) => (props.disabled ? '0.2' : '1')}; + } + + ${StyledCardHeader} { + color: ${(props) => props.theme.textPrimary}; + background: ${(props) => props.colorStatus + ? `rgba(${hex2RGB(props.theme[props.colorStatus]).join(',')}, 0.7)` + : props.theme[props.headerBackgroundColor]}; + + ${(props) => props.disabled && 'opacity: 0.3;'} + } + + ${(props) => props.onClick && !props.disabled + ? css ` + cursor: pointer; + + &:hover { + box-shadow: 0 0 0 2px ${props.theme.highlight}; + } + + &:focus { + ${FocusVisibleStyle} + } + ` + : ''}; + + &.active { + box-shadow: 0 0 0 1px + ${(props) => props.theme[props.activeBorderColor || 'selectedActive']}; + } +`; +function Card({ width = 'auto', height = 'auto', headerBackgroundColor = 'buttonSecondary', bodyBackgroundColor = 'backgroundLevel3', status = null, onClick = null, active = false, disabled = false, children, className, ...rest }) { + let colorStatus = null; + if (status) { + colorStatus = + status != 'healthy' && + 'status' + status.replace(/^\w/, (c) => c.toUpperCase()); + } + return (_jsx(CardContext.Provider, { value: true, children: _jsx(StyledCard, { className: [`sc-card ${active ? 'active' : ''}`, className].join(' '), width: width, height: height, headerBackgroundColor: headerBackgroundColor, bodyBackgroundColor: bodyBackgroundColor, colorStatus: colorStatus, activeBorderColor: !status || status === 'healthy' ? 'selectedActive' : colorStatus, disabled: disabled, role: onClick && !disabled ? 'button' : null, "aria-pressed": onClick && !disabled ? active : null, tabIndex: onClick && !disabled ? 0 : null, onClick: !disabled ? onClick : undefined, active: active, onKeyDown: (event) => { + if (!disabled && + (event.key === ' ' || + event.key === 'Enter' || + event.key === 'Spacebar')) { + event.preventDefault(); + onClick(); + } + }, ...rest, children: children }) })); +} +Card.Header = CardHeader; +Card.Body = CardBody; +Card.BodyContainer = CardBodyContainer; +export { Card }; diff --git a/dist/components/checkbox/Checkbox.component.d.ts b/dist/components/checkbox/Checkbox.component.d.ts new file mode 100644 index 0000000000..b4d2739cad --- /dev/null +++ b/dist/components/checkbox/Checkbox.component.d.ts @@ -0,0 +1,17 @@ +import { ChangeEvent, InputHTMLAttributes } from 'react'; +export type Props = { + label?: string; + value?: string; + checked?: boolean; + disabled?: boolean; + onChange?: (e: ChangeEvent) => void; +} & InputHTMLAttributes; +declare const Checkbox: import("react").ForwardRefExoticComponent<{ + label?: string; + value?: string; + checked?: boolean; + disabled?: boolean; + onChange?: (e: ChangeEvent) => void; +} & InputHTMLAttributes & import("react").RefAttributes>; +export { Checkbox }; +//# sourceMappingURL=Checkbox.component.d.ts.map \ No newline at end of file diff --git a/dist/components/checkbox/Checkbox.component.d.ts.map b/dist/components/checkbox/Checkbox.component.d.ts.map new file mode 100644 index 0000000000..6c64b4c455 --- /dev/null +++ b/dist/components/checkbox/Checkbox.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Checkbox.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/checkbox/Checkbox.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAc,MAAM,OAAO,CAAC;AAOrE,MAAM,MAAM,KAAK,GAAG;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;CACvD,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;AAE1C,QAAA,MAAM,QAAQ;YAPJ,MAAM;YACN,MAAM;cACJ,OAAO;eACN,OAAO;eACP,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI;4FA0BtD,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/checkbox/Checkbox.component.js b/dist/components/checkbox/Checkbox.component.js new file mode 100644 index 0000000000..ecb1f44dd3 --- /dev/null +++ b/dist/components/checkbox/Checkbox.component.js @@ -0,0 +1,96 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { forwardRef } from 'react'; +import styled from 'styled-components'; +import { spacing, Stack } from '../../spacing'; +import { Text } from '../text/Text.component'; +import { FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +const Checkbox = forwardRef(({ disabled, checked, label, value, onChange, ...rest }, ref) => { + return (_jsx(StyledCheckbox, { checked: checked, disabled: disabled, className: "sc-checkbox", children: _jsxs(Stack, { children: [_jsx("input", { type: "checkbox", checked: checked, disabled: disabled, value: value, onChange: onChange, ref: ref, ...rest }), label && _jsx(Text, { children: label })] }) })); +}); +export { Checkbox }; +const StyledCheckbox = styled.label ` + ${(props) => (props.disabled ? 'opacity: 0.5;' : '')} + /* Basic styling */ + + [type='checkbox'] { + width: 0.75rem; + height: 0.75rem; + color: ${(props) => props.theme.textPrimary}; + vertical-align: middle; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: none; + border: 0; + outline: 0; + flex-grow: 0; + border-radius: ${spacing.r2}; + background-color: ${(props) => props.theme.backgroundLevel1}; + transition: background 300ms; + cursor: pointer; + } + + /* Pseudo element for check styling */ + + [type='checkbox']::before { + content: ''; + color: transparent; + display: block; + width: inherit; + height: inherit; + border-radius: inherit; + border: 0; + background-color: transparent; + background-size: contain; + box-shadow: inset 0 0 0 ${spacing.r1} + ${(props) => props.theme.textSecondary}; + } + + /* Checked */ + + [type='checkbox']:checked { + background-color: ${(props) => props.theme.selectedActive}; + } + + [type='checkbox']:checked::before { + box-shadow: none; + background-image: url('data:image/svg+xml,%3Csvg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg"%3E %3Cpath d="M3 6.68646L5.0671 9L9 3" stroke="${(props) => props.theme.textPrimary.replace('#', '%23')}" stroke-width="1.5"/%3E %3C/svg%3E'); + background-repeat: no-repeat; + background-position: center; + } + + /* Indeterminate */ + + [type='checkbox']:indeterminate::before { + box-shadow: inset 0 0 0 ${spacing.r1} + ${(props) => props.theme.selectedActive}; + background-color: ${(props) => props.theme.highlight}; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E %3Cline x1='6' y1='12' x2='20' y2='12' style='stroke:${(props) => props.theme.textPrimary.replace('#', '%23')};stroke-width:4'/%3E %3C/svg%3E"); + } + + /* Hover & focus */ + [type='checkbox']:hover { + ${(props) => !props.disabled && `background-color: ${props.theme.highlight};`} + } + + [type='checkbox']:hover::before { + ${(props) => !props.disabled && + `box-shadow: inset 0 0 0 ${spacing.r1} ${props.theme.selectedActive};`} + } + + [type='checkbox']:focus-visible:enabled { + ${FocusVisibleStyle} + } + + /* Disabled */ + + [type='checkbox']:checked:disabled { + cursor: not-allowed; + background-color: ${(props) => props.theme.selectedActive}; + } + + [type='checkbox']:not(:checked):disabled { + cursor: not-allowed; + background-color: ${(props) => props.theme.textSecondary}; + } +`; diff --git a/dist/components/chips/Chips.component.d.ts b/dist/components/chips/Chips.component.d.ts new file mode 100644 index 0000000000..3d16db1b5c --- /dev/null +++ b/dist/components/chips/Chips.component.d.ts @@ -0,0 +1,21 @@ +import { Size } from '../constants'; +type Props = { + text: string; + variant?: 'statusHealthy' | 'statusWarning' | 'statusCritical' | 'infoPrimary' | 'infoSecondary'; + icon?: JSX.Element; + onClick?: (arg0: any) => void; + onRemove?: (arg0: any) => void; + size?: Size; +}; +export declare const ChipsIcon: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, { + variant: any; + text: string; + size: Size; +}, never>; +export declare const ChipsText: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, { + icon: any; + isRemovable: boolean; +}, never>; +declare const Chips: ({ text, variant, icon, onClick, onRemove, size, }: Props) => import("react/jsx-runtime").JSX.Element; +export { Chips }; +//# sourceMappingURL=Chips.component.d.ts.map \ No newline at end of file diff --git a/dist/components/chips/Chips.component.d.ts.map b/dist/components/chips/Chips.component.d.ts.map new file mode 100644 index 0000000000..823cf5ae3e --- /dev/null +++ b/dist/components/chips/Chips.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Chips.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/chips/Chips.component.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAGpC,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EACJ,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,aAAa,GACb,eAAe,CAAC;IACpB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,IAAI,CAAC,EAAE,IAAI,CAAC;CACb,CAAC;AA0FF,eAAO,MAAM,SAAS;aACX,GAAG;UACN,MAAM;UACN,IAAI;SAOX,CAAC;AACF,eAAO,MAAM,SAAS;UAAuB,GAAG;iBAAe,OAAO;SAKrE,CAAC;AAEF,QAAA,MAAM,KAAK,sDAOR,KAAK,4CAgCP,CAAC;AAEF,OAAO,EAAE,KAAK,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/chips/Chips.component.js b/dist/components/chips/Chips.component.js new file mode 100644 index 0000000000..d9d15b0e7c --- /dev/null +++ b/dist/components/chips/Chips.component.js @@ -0,0 +1,105 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { lighten } from 'polished'; +import styled, { css } from 'styled-components'; +import { fontSize, grayLight, white } from '../../style/theme'; +import { Button } from '../button/Button.component'; +import { Icon } from '../icon/Icon.component'; +const ChipsContainer = styled.div ` + display: inline-flex; + .sc-chips-remove { + padding-right: 10px; + color: ${white}; + &:hover { + color: ${grayLight}; + } + } + ${(props) => { + switch (props.size) { + case 'smaller': + return css ` + border-radius: 10px; + .sc-chips-icon { + border-radius: 10px; + padding: 5px; + } + `; + case 'small': + return css ` + border-radius: 12px; + .sc-chips-icon { + border-radius: 12px; + padding: 6px; + } + `; + case 'large': + return css ` + border-radius: 14px; + .sc-chips-icon { + border-radius: 14px; + padding: 6px; + } + `; + case 'larger': + return css ` + border-radius: 17px; + .sc-chips-icon { + border-radius: 17px; + padding: 7px; + } + `; + default: + return css ` + border-radius: 12px; + .sc-chips-icon { + border-radius: 12px; + padding: 6px; + } + `; + } +}} + ${(props) => { + const brand = props.theme; + return css ` + color: ${brand.textReverse}; + `; +}} + + ${(props) => { + const brand = props.theme; + const brandLight = lighten(0.1, brand[props.variant]).toString(); + return props.onClick + ? css ` + background-color: ${brand[props.variant]}; + font-size: ${fontSize[props.size || 'base']}; + &:hover { + cursor: pointer; + background-color: ${brandLight}; + } + &:active { + background-color: ${brand[props.variant]}; + } + ` + : css ` + background-color: ${brand[props.variant]}; + font-size: ${fontSize[props.size || 'base']}; + `; +}} +`; +export const ChipsIcon = styled.span ` + display: inline-flex; + justify-content: center; + align-items: center; + background-color: ${(props) => lighten(0.15, props.theme[props.variant]).toString()}; +`; +export const ChipsText = styled.span ` + display: inline-flex; + justify-content: center; + align-items: center; + padding: ${(props) => (props.icon || props.isRemovable ? '5px' : '5px 10px')}; +`; +const Chips = ({ text = '', variant = 'infoPrimary', icon = undefined, onClick, onRemove, size = 'base', }) => (_jsxs(ChipsContainer, { className: "sc-chips", onClick: onClick, variant: variant, icon: icon, size: size, children: [icon && (_jsx(ChipsIcon, { className: "sc-chips-icon", text: text, variant: variant, size: size, children: icon })), _jsx(ChipsText, { className: "sc-chips-text", icon: icon, isRemovable: !!onRemove, children: text }), onRemove && (_jsx(Button + // @ts-ignore + , { + // @ts-ignore + className: "sc-chips-remove", size: size, inverted: true, icon: _jsx(Icon, { name: "Close" }), onClick: onRemove }))] })); +export { Chips }; diff --git a/dist/components/circularprogressbar/CircularProgressBar.component.d.ts b/dist/components/circularprogressbar/CircularProgressBar.component.d.ts new file mode 100644 index 0000000000..024e2091bf --- /dev/null +++ b/dist/components/circularprogressbar/CircularProgressBar.component.d.ts @@ -0,0 +1,12 @@ +type Props = { + percent: number; + radius: number; + strokeWidth?: number; + title?: string; + color?: string; + backgroundColor?: string; + children?: JSX.Element; +}; +declare function CircularProgressBar({ percent, radius, strokeWidth, title, color, backgroundColor, children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { CircularProgressBar }; +//# sourceMappingURL=CircularProgressBar.component.d.ts.map \ No newline at end of file diff --git a/dist/components/circularprogressbar/CircularProgressBar.component.d.ts.map b/dist/components/circularprogressbar/CircularProgressBar.component.d.ts.map new file mode 100644 index 0000000000..a80a9cee73 --- /dev/null +++ b/dist/components/circularprogressbar/CircularProgressBar.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"CircularProgressBar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/circularprogressbar/CircularProgressBar.component.tsx"],"names":[],"mappings":"AAMA,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACxB,CAAC;AAEF,iBAAS,mBAAmB,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,WAAgB,EAChB,KAAK,EACL,KAAK,EACL,eAAe,EACf,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,KAAK,2CA8BP;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/circularprogressbar/CircularProgressBar.component.js b/dist/components/circularprogressbar/CircularProgressBar.component.js new file mode 100644 index 0000000000..ddcc9d183c --- /dev/null +++ b/dist/components/circularprogressbar/CircularProgressBar.component.js @@ -0,0 +1,9 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { CircularProgressBarContainer, Title, ProgressCircle, BackgroundCircle, } from './CircularProgressBar.component.style'; +function CircularProgressBar({ percent, radius, strokeWidth = 10, title, color, backgroundColor, children, ...rest }) { + const centerPointCoordinate = strokeWidth / 2 + radius; + const svgSize = centerPointCoordinate * 2; + const CIRCUMFERENCE = Math.PI * (radius * 2); + return (_jsxs(CircularProgressBarContainer, { className: "sc-circularprogressbar", ...rest, children: [title && _jsx(Title, { children: title }), _jsxs("svg", { width: svgSize, height: svgSize, children: [_jsx(BackgroundCircle, { cx: centerPointCoordinate, cy: centerPointCoordinate, backgroundColor: backgroundColor, r: radius, strokeWidth: strokeWidth }), _jsx(ProgressCircle, { percent: percent, color: color, circumference: CIRCUMFERENCE, cx: centerPointCoordinate, cy: centerPointCoordinate, r: radius, strokeWidth: strokeWidth, transform: `rotate(-90 ${centerPointCoordinate} ${centerPointCoordinate})` }), children] })] })); +} +export { CircularProgressBar }; diff --git a/dist/components/circularprogressbar/CircularProgressBar.component.style.d.ts b/dist/components/circularprogressbar/CircularProgressBar.component.style.d.ts new file mode 100644 index 0000000000..9a5babb6a0 --- /dev/null +++ b/dist/components/circularprogressbar/CircularProgressBar.component.style.d.ts @@ -0,0 +1,11 @@ +import { EmphaseText } from '../text/Text.component'; +export declare const CircularProgressBarContainer: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const Title: import("styled-components").StyledComponent; +export declare const ProgressCircle: import("styled-components").StyledComponent<"circle", import("styled-components").DefaultTheme, { + circumference: number; + percent: number; +}, never>; +export declare const BackgroundCircle: import("styled-components").StyledComponent<"circle", import("styled-components").DefaultTheme, { + backgroundColor?: string; +}, never>; +//# sourceMappingURL=CircularProgressBar.component.style.d.ts.map \ No newline at end of file diff --git a/dist/components/circularprogressbar/CircularProgressBar.component.style.d.ts.map b/dist/components/circularprogressbar/CircularProgressBar.component.style.d.ts.map new file mode 100644 index 0000000000..ecbd7cd3fa --- /dev/null +++ b/dist/components/circularprogressbar/CircularProgressBar.component.style.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"CircularProgressBar.component.style.d.ts","sourceRoot":"","sources":["../../../src/lib/components/circularprogressbar/CircularProgressBar.component.style.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,eAAO,MAAM,4BAA4B,yGAGxC,CAAC;AACF,eAAO,MAAM,KAAK,sHAKjB,CAAC;AACF,eAAO,MAAM,cAAc;mBACV,MAAM;aACZ,MAAM;SAShB,CAAC;AACF,eAAO,MAAM,gBAAgB;sBAAqC,MAAM;SAIvE,CAAC"} \ No newline at end of file diff --git a/dist/components/circularprogressbar/CircularProgressBar.component.style.js b/dist/components/circularprogressbar/CircularProgressBar.component.style.js new file mode 100644 index 0000000000..7700b7e9b5 --- /dev/null +++ b/dist/components/circularprogressbar/CircularProgressBar.component.style.js @@ -0,0 +1,27 @@ +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { getThemePropSelector } from '../../utils'; +import { EmphaseText } from '../text/Text.component'; +export const CircularProgressBarContainer = styled.div ` + display: inline-block; + color: ${getThemePropSelector('textPrimary')}; +`; +export const Title = styled(EmphaseText) ` + display: flex; + justify-content: center; + align-items: center; + padding: ${spacing.r8}; +`; +export const ProgressCircle = styled.circle ` + stroke-dasharray: ${({ circumference }) => circumference}; + stroke-dashoffset: ${({ percent, circumference }) => ((100 - percent) / 100) * circumference}; + stroke: ${(props) => props.color || props.theme.statusHealthy}; + stroke-width: ${(props) => props.strokeWidth}; + stroke-linecap: round; + fill: none; +`; +export const BackgroundCircle = styled.circle ` + fill: none; + stroke: ${(props) => props.backgroundColor || props.theme.backgroundLevel1}; + stroke-width: ${(props) => props.strokeWidth}; +`; diff --git a/dist/components/cloudprogressbar/CloudProgressBar.component.d.ts b/dist/components/cloudprogressbar/CloudProgressBar.component.d.ts new file mode 100644 index 0000000000..d8e265e983 --- /dev/null +++ b/dist/components/cloudprogressbar/CloudProgressBar.component.d.ts @@ -0,0 +1,10 @@ +export type CloudProgressBarProps = { + percentage: number; + borderSize: string; + cloudColor?: string; + progressCloudColor?: string; + children: JSX.Element; +}; +declare const CloudProgressBar: ({ percentage, borderSize, cloudColor, progressCloudColor, children, }: CloudProgressBarProps) => import("react/jsx-runtime").JSX.Element; +export { CloudProgressBar }; +//# sourceMappingURL=CloudProgressBar.component.d.ts.map \ No newline at end of file diff --git a/dist/components/cloudprogressbar/CloudProgressBar.component.d.ts.map b/dist/components/cloudprogressbar/CloudProgressBar.component.d.ts.map new file mode 100644 index 0000000000..8d2e7c9512 --- /dev/null +++ b/dist/components/cloudprogressbar/CloudProgressBar.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"CloudProgressBar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/cloudprogressbar/CloudProgressBar.component.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,CAAC;AA6EF,QAAA,MAAM,gBAAgB,0EAMnB,qBAAqB,4CAWvB,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/cloudprogressbar/CloudProgressBar.component.js b/dist/components/cloudprogressbar/CloudProgressBar.component.js new file mode 100644 index 0000000000..91c07947ef --- /dev/null +++ b/dist/components/cloudprogressbar/CloudProgressBar.component.js @@ -0,0 +1,38 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css, keyframes } from 'styled-components'; +import { coreUIAvailableThemes } from '../../style/theme'; +const keyFrameCloud = (props) => { + return keyframes ` + from { + height:100% + } + to { + height:${100 - props.percentage}% + }`; +}; +const Container = styled.div ` + ${(props) => { + return css ` + text-align: center; + position: relative; + `; +}} +`; +const ContainerProgress = styled.div ` + ${(props) => { + return css ` + animation-duration: 1s; + animation-fill-mode: both; + animation-name: ${keyFrameCloud}; + position: absolute; + top: 0; + left: 0; + width: 100%; + overflow: hidden; + `; +}} +`; +const Cloud = ({ strokeColor, borderSize }) => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 15 72 42", enableBackground: "new 0 0 72 72", children: _jsx("g", { children: _jsx("path", { fill: "none", stroke: strokeColor, strokeWidth: borderSize, strokeLinecap: "round", strokeLinejoin: "round", strokeMiterlimit: "10", d: "M15.9,30.3c0,0.4-0.4,0.8-0.8,0.8C10,31.6,6,36.7,6,42.9c0,6.6,4.5,11.9,10.2,11.9h38.7C61,54.8,66,49.1,66,42.2c0-6.6-4.6-12.1-10.4-12.5c-0.4,0-0.8-0.3-0.9-0.8c-1.3-6.7-7.3-11.7-14.3-11.7c-4.6,0-8.7,2.1-11.3,5.4C28.8,23,28.3,23.1,28,23c-1-0.4-2.1-0.6-3.3-0.6C20.1,22.3,16.3,25.8,15.9,30.3z" }) }) })); +const CloudProgress = ({ strokeColor, percentage, borderSize }) => (_jsx(ContainerProgress, { percentage: percentage, children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 15 72 42", enableBackground: "new 0 0 72 72", children: _jsx("g", { children: _jsx("path", { fill: "none", stroke: strokeColor, strokeWidth: borderSize, strokeLinecap: "round", strokeLinejoin: "round", strokeMiterlimit: "10", d: "M15.9,30.3c0,0.4-0.4,0.8-0.8,0.8C10,31.6,6,36.7,6,42.9c0,6.6,4.5,11.9,10.2,11.9h38.7C61,54.8,66,49.1,66,42.2c0-6.6-4.6-12.1-10.4-12.5c-0.4,0-0.8-0.3-0.9-0.8c-1.3-6.7-7.3-11.7-14.3-11.7c-4.6,0-8.7,2.1-11.3,5.4C28.8,23,28.3,23.1,28,23c-1-0.4-2.1-0.6-3.3-0.6C20.1,22.3,16.3,25.8,15.9,30.3z" }) }) }) })); +const CloudProgressBar = ({ percentage = 0, borderSize = '2px', cloudColor = coreUIAvailableThemes.darkRebrand.statusHealthy, progressCloudColor = coreUIAvailableThemes.darkRebrand.backgroundLevel1, children, }) => (_jsxs(Container, { className: "sc-cloudprogressbar", children: [_jsx(Cloud, { strokeColor: progressCloudColor, borderSize: borderSize }), _jsx(CloudProgress, { strokeColor: cloudColor, percentage: percentage, borderSize: borderSize }), children] })); +export { CloudProgressBar }; diff --git a/dist/components/collapsiblepanel/CollapsiblePanel.component.d.ts b/dist/components/collapsiblepanel/CollapsiblePanel.component.d.ts new file mode 100644 index 0000000000..9977ed9b5d --- /dev/null +++ b/dist/components/collapsiblepanel/CollapsiblePanel.component.d.ts @@ -0,0 +1,9 @@ +type Props = { + expanded: boolean; + onHeaderClick: (arg0: any) => void; + children: React.ReactNode; + headerItems: Array; +}; +declare function CollapsiblePanel({ expanded, onHeaderClick, children, headerItems, }: Props): import("react/jsx-runtime").JSX.Element; +export { CollapsiblePanel }; +//# sourceMappingURL=CollapsiblePanel.component.d.ts.map \ No newline at end of file diff --git a/dist/components/collapsiblepanel/CollapsiblePanel.component.d.ts.map b/dist/components/collapsiblepanel/CollapsiblePanel.component.d.ts.map new file mode 100644 index 0000000000..7f85246fa1 --- /dev/null +++ b/dist/components/collapsiblepanel/CollapsiblePanel.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"CollapsiblePanel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/collapsiblepanel/CollapsiblePanel.component.tsx"],"names":[],"mappings":"AAIA,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;CACjC,CAAC;AAqCF,iBAAS,gBAAgB,CAAC,EACxB,QAAgB,EAChB,aAAa,EACb,QAAQ,EACR,WAAgB,GACjB,EAAE,KAAK,2CAuBP;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/collapsiblepanel/CollapsiblePanel.component.js b/dist/components/collapsiblepanel/CollapsiblePanel.component.js new file mode 100644 index 0000000000..49765e2a90 --- /dev/null +++ b/dist/components/collapsiblepanel/CollapsiblePanel.component.js @@ -0,0 +1,44 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize } from '../../style/theme'; +import { Icon } from '../icon/Icon.component'; +const ARROW = { + colapsed: 'fas fa-angle-down', + expanded: 'fas fa-angle-up', +}; +const HeaderText = styled.div ` + display: flex; + align-items: center; + flex-grow: 1; +`; +const HeaderItem = styled.div ` + margin-right: ${spacing.r16}; + display: flex; + flex-grow: 1; +`; +const HeaderIcon = styled.div ` + font-size: ${fontSize.larger}; + margin: 0 ${spacing.r16}; +`; +const CollapsiblePanelContainer = styled.div ` + display: flex; + flex-direction: column; + border-radius: 4px; + background-color: ${(props) => props.theme.backgroundLevel1}; + color: ${(props) => props.theme.textPrimary}; +`; +const HeaderContainer = styled.div ` + display: flex; + cursor: pointer; + padding: ${spacing.r16}; +`; +const ExpandedContainer = styled.div ` + padding: ${spacing.r16}; + color: ${(props) => props.theme.textPrimary}; + background-color: ${(props) => props.theme.backgroundLevel1}; +`; +function CollapsiblePanel({ expanded = false, onHeaderClick, children, headerItems = [], }) { + return (_jsxs(CollapsiblePanelContainer, { className: "sc-collapsiblepanel", children: [_jsxs(HeaderContainer, { onClick: onHeaderClick, className: "sc-collapsiblepanel-header", children: [_jsx(HeaderText, { children: headerItems.map((item, index) => (_jsx(HeaderItem, { children: item }, index))) }), _jsx(HeaderIcon, { children: _jsx(Icon, { name: expanded ? 'Dropdown-up' : 'Dropdown-down' }) })] }), expanded && (_jsx(ExpandedContainer, { className: "sc-collapsiblepanel-content", children: children }))] })); +} +export { CollapsiblePanel }; diff --git a/dist/components/constants.d.ts b/dist/components/constants.d.ts new file mode 100644 index 0000000000..d9408d21c8 --- /dev/null +++ b/dist/components/constants.d.ts @@ -0,0 +1,34 @@ +export declare const LOADER_SIZE: { + [Key in Size]: Key; +}; +export type Size = 'smaller' | 'small' | 'base' | 'large' | 'larger' | 'huge' | 'massive'; +export type Variant = 'base' | 'selected' | 'healthy' | 'warning' | 'danger'; +export declare const QUERY_LAST_SEVEN_DAYS = "now-7d"; +export declare const QUERY_LAST_TWENTY_FOUR_HOURS = "now-24h"; +export declare const QUERY_LAST_ONE_HOUR = "now-1h"; +export declare const LAST_SEVEN_DAYS = "Last 7 days"; +export declare const LAST_TWENTY_FOUR_HOURS = "Last 24 hours"; +export declare const LAST_ONE_HOUR = "Last 1 hour"; +export declare const SAMPLE_DURATION_LAST_SEVEN_DAYS: number; +export declare const SAMPLE_DURATION_LAST_TWENTY_FOUR_HOURS: number; +export declare const SAMPLE_DURATION_LAST_ONE_HOUR: number; +export declare const SAMPLE_FREQUENCY_LAST_SEVEN_DAYS: number; +export declare const SAMPLE_FREQUENCY_LAST_TWENTY_FOUR_HOURS = 720; +export declare const SAMPLE_FREQUENCY_LAST_ONE_HOUR = 30; +export type QueryTimeSpan = { + query: string; + label: string; + duration: number; + frequency: number; +}; +export declare const queryTimeSpansCodes: QueryTimeSpan[]; +export declare const NAN_STRING = "NAN"; +export declare const STATUS_CRITICAL = "critical"; +export declare const STATUS_WARNING = "warning"; +export declare const STATUS_SUCCESS = "success"; +export declare const STATUS_HEALTHY = "healthy"; +export declare const STATUS_INFO = "info"; +export declare const STATUS_UNKNOWN = "unknown"; +export declare const STATUS_NONE = "none"; +export type Status = 'none' | 'unknown' | 'info' | 'healthy' | 'success' | 'warning' | 'critical'; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/components/constants.d.ts.map b/dist/components/constants.d.ts.map new file mode 100644 index 0000000000..ee1ff64406 --- /dev/null +++ b/dist/components/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/components/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,EAAE;KAAG,GAAG,IAAI,IAAI,GAAG,GAAG;CAQ7C,CAAC;AACF,MAAM,MAAM,IAAI,GACZ,SAAS,GACT,OAAO,GACP,MAAM,GACN,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAG7E,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,4BAA4B,YAAY,CAAC;AACtD,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAE5C,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAE3C,eAAO,MAAM,+BAA+B,QAAmB,CAAC;AAChE,eAAO,MAAM,sCAAsC,QAAe,CAAC;AACnE,eAAO,MAAM,6BAA6B,QAAU,CAAC;AAErD,eAAO,MAAM,gCAAgC,QAAU,CAAC;AACxD,eAAO,MAAM,uCAAuC,MAAM,CAAC;AAC3D,eAAO,MAAM,8BAA8B,KAAK,CAAC;AACjD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,MAAM,CAAC;IAEd,QAAQ,EAAE,MAAM,CAAC;IAEjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,eAAO,MAAM,mBAAmB,EAAE,aAAa,EAmB9C,CAAC;AACF,eAAO,MAAM,UAAU,QAAQ,CAAC;AAEhC,eAAO,MAAM,eAAe,aAAa,CAAC;AAC1C,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,WAAW,SAAS,CAAC;AAClC,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,WAAW,SAAS,CAAC;AAElC,MAAM,MAAM,MAAM,GACd,MAAM,GACN,SAAS,GACT,MAAM,GACN,SAAS,GACT,SAAS,GACT,SAAS,GACT,UAAU,CAAC"} \ No newline at end of file diff --git a/dist/components/constants.js b/dist/components/constants.js new file mode 100644 index 0000000000..26b6746cca --- /dev/null +++ b/dist/components/constants.js @@ -0,0 +1,54 @@ +export const LOADER_SIZE = { + smaller: 'smaller', + small: 'small', + base: 'base', + large: 'large', + larger: 'larger', + huge: 'huge', + massive: 'massive', +}; +// metric chart +// url query +export const QUERY_LAST_SEVEN_DAYS = 'now-7d'; +export const QUERY_LAST_TWENTY_FOUR_HOURS = 'now-24h'; +export const QUERY_LAST_ONE_HOUR = 'now-1h'; +// label in timespan selector +export const LAST_SEVEN_DAYS = 'Last 7 days'; +export const LAST_TWENTY_FOUR_HOURS = 'Last 24 hours'; +export const LAST_ONE_HOUR = 'Last 1 hour'; +// sample duration +export const SAMPLE_DURATION_LAST_SEVEN_DAYS = 7 * 24 * 60 * 60; +export const SAMPLE_DURATION_LAST_TWENTY_FOUR_HOURS = 24 * 60 * 60; +export const SAMPLE_DURATION_LAST_ONE_HOUR = 60 * 60; +// sample frequency +export const SAMPLE_FREQUENCY_LAST_SEVEN_DAYS = 60 * 60; +export const SAMPLE_FREQUENCY_LAST_TWENTY_FOUR_HOURS = 720; +export const SAMPLE_FREQUENCY_LAST_ONE_HOUR = 30; +export const queryTimeSpansCodes = [ + { + query: QUERY_LAST_SEVEN_DAYS, + label: LAST_SEVEN_DAYS, + duration: SAMPLE_DURATION_LAST_SEVEN_DAYS, + frequency: SAMPLE_FREQUENCY_LAST_SEVEN_DAYS, + }, + { + query: QUERY_LAST_TWENTY_FOUR_HOURS, + label: LAST_TWENTY_FOUR_HOURS, + duration: SAMPLE_DURATION_LAST_TWENTY_FOUR_HOURS, + frequency: SAMPLE_FREQUENCY_LAST_TWENTY_FOUR_HOURS, + }, + { + query: QUERY_LAST_ONE_HOUR, + label: LAST_ONE_HOUR, + duration: SAMPLE_DURATION_LAST_ONE_HOUR, + frequency: SAMPLE_FREQUENCY_LAST_ONE_HOUR, + }, +]; +export const NAN_STRING = 'NAN'; +export const STATUS_CRITICAL = 'critical'; +export const STATUS_WARNING = 'warning'; +export const STATUS_SUCCESS = 'success'; +export const STATUS_HEALTHY = 'healthy'; +export const STATUS_INFO = 'info'; +export const STATUS_UNKNOWN = 'unknown'; +export const STATUS_NONE = 'none'; diff --git a/dist/components/constrainedtext/Constrainedtext.component.d.ts b/dist/components/constrainedtext/Constrainedtext.component.d.ts new file mode 100644 index 0000000000..c37536b8fe --- /dev/null +++ b/dist/components/constrainedtext/Constrainedtext.component.d.ts @@ -0,0 +1,11 @@ +import { $PropertyType } from 'utility-types'; +import { Props as TooltipProps } from '../tooltip/Tooltip.component'; +type Props = { + text: string | number | JSX.Element | JSX.Element[]; + tooltipStyle?: $PropertyType; + tooltipPlacement?: $PropertyType; + lineClamp?: number; +}; +declare function ConstrainedText({ text, tooltipStyle, tooltipPlacement, lineClamp, }: Props): JSX.Element; +export { ConstrainedText }; +//# sourceMappingURL=Constrainedtext.component.d.ts.map \ No newline at end of file diff --git a/dist/components/constrainedtext/Constrainedtext.component.d.ts.map b/dist/components/constrainedtext/Constrainedtext.component.d.ts.map new file mode 100644 index 0000000000..8e40e0d3d0 --- /dev/null +++ b/dist/components/constrainedtext/Constrainedtext.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Constrainedtext.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/constrainedtext/Constrainedtext.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAK9C,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAErE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACpD,YAAY,CAAC,EAAE,aAAa,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAC3D,gBAAgB,CAAC,EAAE,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAiDF,iBAAS,eAAe,CAAC,EACvB,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,SAAa,GACd,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAuBrB;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/constrainedtext/Constrainedtext.component.js b/dist/components/constrainedtext/Constrainedtext.component.js new file mode 100644 index 0000000000..cf0d1c539b --- /dev/null +++ b/dist/components/constrainedtext/Constrainedtext.component.js @@ -0,0 +1,46 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { useCallback, useState } from 'react'; +import styled from 'styled-components'; +import { Tooltip } from '../tooltip/Tooltip.component'; +// for lineClamp cf https://css-tricks.com/almanac/properties/l/line-clamp/ +// it should work on all major navigator, despite the --webkit prefix +// just in case if we don't use line clamp we can just use the classic way +const ConstrainedTextContainer = styled.div ` + overflow: hidden; + text-overflow: ellipsis; + + ${(props) => props.lineClamp > 1 + ? ` + display: -webkit-box; + -webkit-line-clamp: ${props.lineClamp}; + -webkit-box-orient: vertical; + overflow-wrap: break-word; + word-break: break-all; + ` + : `overflow-wrap: break-word; + white-space: nowrap; + word-break: break-all; + `}; +`; +const BlockTooltip = styled.div ` + width: stretch; + & > .sc-tooltip { + display: block; + } +`; +function isEllipsisActive(element) { + return (element && + (element.offsetWidth < element.scrollWidth || + element.offsetHeight < element.scrollHeight)); +} +function getConstrainedTextContainer(constrainedTextRef, lineClamp, text) { + return (_jsx(ConstrainedTextContainer, { ref: constrainedTextRef, className: "sc-constrainedtext", lineClamp: lineClamp, children: text })); +} +function ConstrainedText({ text, tooltipStyle, tooltipPlacement, lineClamp = 1, }) { + const [displayToolTip, setDisplayToolTip] = useState(false); + const constrainedTextRef = useCallback((element) => { + element && text && setDisplayToolTip(isEllipsisActive(element)); + }, [text]); + return (_jsx(BlockTooltip, { children: displayToolTip ? (_jsx(Tooltip, { overlay: text, overlayStyle: tooltipStyle, placement: tooltipPlacement, children: getConstrainedTextContainer(constrainedTextRef, lineClamp, text) })) : (getConstrainedTextContainer(constrainedTextRef, lineClamp, text)) })); +} +export { ConstrainedText }; diff --git a/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts b/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts new file mode 100644 index 0000000000..19fb4bc149 --- /dev/null +++ b/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; +import { CoreUITheme } from '../../style/theme'; +type Props = { + theme: CoreUITheme; + children: React.ReactNode; +}; +declare const CoreUiThemeProvider: ({ theme, children }: Props) => import("react/jsx-runtime").JSX.Element; +export { CoreUiThemeProvider }; +//# sourceMappingURL=CoreUiThemeProvider.d.ts.map \ No newline at end of file diff --git a/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts.map b/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts.map new file mode 100644 index 0000000000..e0ccdc4309 --- /dev/null +++ b/dist/components/coreuithemeprovider/CoreUiThemeProvider.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"CoreUiThemeProvider.d.ts","sourceRoot":"","sources":["../../../src/lib/components/coreuithemeprovider/CoreUiThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAmB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEjE,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,QAAA,MAAM,mBAAmB,wBAAyB,KAAK,4CAStD,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/coreuithemeprovider/CoreUiThemeProvider.js b/dist/components/coreuithemeprovider/CoreUiThemeProvider.js new file mode 100644 index 0000000000..a355cebff9 --- /dev/null +++ b/dist/components/coreuithemeprovider/CoreUiThemeProvider.js @@ -0,0 +1,13 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { ThemeProvider } from 'styled-components'; +import { space, fontSize } from '../../style/theme'; +const CoreUiThemeProvider = ({ theme, children }) => { + const newTheme = { + ...theme, + space, + fontSizes: fontSize, + colors: { ...theme }, + }; + return _jsx(ThemeProvider, { theme: newTheme, children: children }); +}; +export { CoreUiThemeProvider }; diff --git a/dist/components/date/FormattedDateTime.d.ts b/dist/components/date/FormattedDateTime.d.ts new file mode 100644 index 0000000000..7762930e60 --- /dev/null +++ b/dist/components/date/FormattedDateTime.d.ts @@ -0,0 +1,10 @@ +export declare const DATE_FORMATER: Intl.DateTimeFormat; +export declare const TIME_SECOND_FORMATER: Intl.DateTimeFormat; +export declare const TIME_FORMATER: Intl.DateTimeFormat; +type FormattedDateTimeProps = { + format: 'date' | 'date-time' | 'date-time-second' | 'time' | 'time-second' | 'relative'; + value: Date; +}; +export declare const FormattedDateTime: ({ format, value, }: FormattedDateTimeProps) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=FormattedDateTime.d.ts.map \ No newline at end of file diff --git a/dist/components/date/FormattedDateTime.d.ts.map b/dist/components/date/FormattedDateTime.d.ts.map new file mode 100644 index 0000000000..2759c43b4a --- /dev/null +++ b/dist/components/date/FormattedDateTime.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FormattedDateTime.d.ts","sourceRoot":"","sources":["../../../src/lib/components/date/FormattedDateTime.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,qBAKxB,CAAC;AAEH,eAAO,MAAM,oBAAoB,qBAK/B,CAAC;AAEH,eAAO,MAAM,aAAa,qBAIxB,CAAC;AAEH,KAAK,sBAAsB,GAAG;IAC5B,MAAM,EACF,MAAM,GACN,WAAW,GACX,kBAAkB,GAClB,MAAM,GACN,aAAa,GACb,UAAU,CAAC;IACf,KAAK,EAAE,IAAI,CAAC;CACb,CAAC;AAaF,eAAO,MAAM,iBAAiB,uBAG3B,sBAAsB,4CAqGxB,CAAC"} \ No newline at end of file diff --git a/dist/components/date/FormattedDateTime.js b/dist/components/date/FormattedDateTime.js new file mode 100644 index 0000000000..4fb79eaba2 --- /dev/null +++ b/dist/components/date/FormattedDateTime.js @@ -0,0 +1,66 @@ +import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime"; +import { getDateDaysDiff } from './dateDiffer'; +import { Tooltip } from '../tooltip/Tooltip.component'; +export const DATE_FORMATER = Intl.DateTimeFormat('fr-CA', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour12: false, +}); +export const TIME_SECOND_FORMATER = Intl.DateTimeFormat('en-GB', { + hour12: false, + hour: '2-digit', + minute: '2-digit', + second: '2-digit', +}); +export const TIME_FORMATER = Intl.DateTimeFormat('en-GB', { + hour12: false, + hour: '2-digit', + minute: '2-digit', +}); +const isItFutureOrIsItPast = (timeDiff, stringToBeFormatted) => { + if (timeDiff > 0) { + return `${stringToBeFormatted} ago`; + } + else { + return `in ${stringToBeFormatted}`; + } +}; +export const FormattedDateTime = ({ format, value, }) => { + switch (format) { + case 'date': + return _jsx(_Fragment, { children: DATE_FORMATER.format(value) }); + case 'date-time': + return (_jsx(_Fragment, { children: DATE_FORMATER.format(value) + ' ' + TIME_FORMATER.format(value) })); + case 'date-time-second': + return (_jsx(_Fragment, { children: DATE_FORMATER.format(value) + + ' ' + + TIME_SECOND_FORMATER.format(value) })); + case 'time': + return _jsx(_Fragment, { children: TIME_FORMATER.format(value) }); + case 'time-second': + return _jsx(_Fragment, { children: TIME_SECOND_FORMATER.format(value) }); + case 'relative': + const now = new Date(); + const monthDiff = getDateDaysDiff(value, now, 'months'); + const dayDiff = getDateDaysDiff(value, now, 'days'); + if (monthDiff !== 0 && Math.abs(dayDiff) > 90) { + return (_jsx(Tooltip, { overlay: _jsx(FormattedDateTime, { format: "date-time-second", value: value }), children: isItFutureOrIsItPast(monthDiff, `${Math.abs(monthDiff)} month${Math.abs(monthDiff) > 1 ? 's' : ''}`) })); + } + if (dayDiff !== 0) { + return (_jsx(Tooltip, { overlay: _jsx(FormattedDateTime, { format: "date-time-second", value: value }), children: isItFutureOrIsItPast(dayDiff, `${Math.abs(dayDiff)} day${Math.abs(dayDiff) > 1 ? 's' : ''}`) })); + } + const hourDiff = getDateDaysDiff(value, now, 'hours'); + if (hourDiff !== 0) { + return (_jsx(Tooltip, { overlay: _jsx(FormattedDateTime, { format: "date-time-second", value: value }), children: isItFutureOrIsItPast(hourDiff, `${Math.abs(hourDiff)} hour${Math.abs(hourDiff) > 1 ? 's' : ''}`) })); + } + const minuteDiff = getDateDaysDiff(value, now, 'minutes'); + if (minuteDiff !== 0) { + return (_jsx(Tooltip, { overlay: _jsx(FormattedDateTime, { format: "date-time-second", value: value }), children: isItFutureOrIsItPast(minuteDiff, `${Math.abs(minuteDiff)} minute${Math.abs(minuteDiff) > 1 ? 's' : ''}`) })); + } + return (_jsx(Tooltip, { overlay: _jsx(FormattedDateTime, { format: "date-time-second", value: value }), children: "few seconds ago" })); + //TO FINISH + default: + return _jsx(_Fragment, {}); + } +}; diff --git a/dist/components/date/FormattedDateTime.spec.d.ts b/dist/components/date/FormattedDateTime.spec.d.ts new file mode 100644 index 0000000000..4644a5efde --- /dev/null +++ b/dist/components/date/FormattedDateTime.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=FormattedDateTime.spec.d.ts.map \ No newline at end of file diff --git a/dist/components/date/FormattedDateTime.spec.d.ts.map b/dist/components/date/FormattedDateTime.spec.d.ts.map new file mode 100644 index 0000000000..f49a52c9a4 --- /dev/null +++ b/dist/components/date/FormattedDateTime.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FormattedDateTime.spec.d.ts","sourceRoot":"","sources":["../../../src/lib/components/date/FormattedDateTime.spec.tsx"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/components/date/FormattedDateTime.spec.js b/dist/components/date/FormattedDateTime.spec.js new file mode 100644 index 0000000000..de2ab05696 --- /dev/null +++ b/dist/components/date/FormattedDateTime.spec.js @@ -0,0 +1,140 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { render, screen } from '@testing-library/react'; +import { FormattedDateTime } from './FormattedDateTime'; +import userEvent from '@testing-library/user-event'; +describe('FormatttedDateTime', () => { + it('should display the date in the expected format', () => { + //S + render(_jsx(FormattedDateTime, { format: "date", value: new Date('2022-10-01T00:00:00Z') })); + //V + expect(screen.getByText('2022-10-01')).toBeInTheDocument(); + }); + it('should display the date time second in the expected format', () => { + //S + render(_jsx(FormattedDateTime, { format: "date-time-second", value: new Date('2022-10-01T00:00:00Z') })); + //V + expect(screen.getByText('2022-10-01 00:00:00')).toBeInTheDocument(); + }); + it('should display the date time in the expected format', () => { + //S + render(_jsx(FormattedDateTime, { format: "date-time", value: new Date('2022-10-01T00:00:00Z') })); + //V + expect(screen.getByText('2022-10-01 00:00')).toBeInTheDocument(); + }); + it('should display the time second in the expected format', () => { + //S + render(_jsx(FormattedDateTime, { format: "time-second", value: new Date('2022-10-01T00:00:00Z') })); + //V + expect(screen.getByText('00:00:00')).toBeInTheDocument(); + }); + it('should display the time in the expected format', () => { + //S + render(_jsx(FormattedDateTime, { format: "time", value: new Date('2022-10-01T00:00:00Z') })); + //V + expect(screen.getByText('00:00')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured few seconds before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-10-10T11:59:37Z') })); + //V + expect(screen.getByText('few seconds ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('few seconds ago')); + //V + expect(screen.getByText('2022-10-10 11:59:37')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 1 minute before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-10-10T11:59:00Z') })); + //V + expect(screen.getByText('1 minute ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('1 minute ago')); + //V + expect(screen.getByText('2022-10-10 11:59:00')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 2 minutes before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-10-10T11:57:26Z') })); + //V + expect(screen.getByText('2 minutes ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('2 minutes ago')); + //V + expect(screen.getByText('2022-10-10 11:57:26')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 1 day before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-10-09T11:57:26Z') })); + //V + expect(screen.getByText('1 day ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('1 day ago')); + //V + expect(screen.getByText('2022-10-09 11:57:26')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 2 days before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-10-08T11:57:26Z') })); + //V + expect(screen.getByText('2 days ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('2 days ago')); + //V + expect(screen.getByText('2022-10-08 11:57:26')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 1 month before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-09-08T11:57:26Z') })); + //V + expect(screen.getByText('32 days ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('32 days ago')); + //V + expect(screen.getByText('2022-09-08 11:57:26')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 2 months before', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-08-08T11:57:26Z') })); + //V + expect(screen.getByText('63 days ago')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('63 days ago')); + //V + expect(screen.getByText('2022-08-08 11:57:26')).toBeInTheDocument(); + }); + it('should display a relative date with the right format when the date occured 2 months after', async () => { + //S + const today = new Date('2022-10-10T12:00:00Z'); + jest.useFakeTimers('modern'); + jest.setSystemTime(today); + render(_jsx(FormattedDateTime, { format: "relative", value: new Date('2022-12-12T11:57:26Z') })); + //V + expect(screen.getByText('in 63 days')).toBeInTheDocument(); + //E + await userEvent.hover(screen.getByText('in 63 days')); + //V + expect(screen.getByText('2022-12-12 11:57:26')).toBeInTheDocument(); + }); +}); diff --git a/dist/components/date/dateDiffer.d.ts b/dist/components/date/dateDiffer.d.ts new file mode 100644 index 0000000000..945e35b2bb --- /dev/null +++ b/dist/components/date/dateDiffer.d.ts @@ -0,0 +1,2 @@ +export declare function getDateDaysDiff(startDate: Date, endDate: Date, unit: 'months' | 'days' | 'hours' | 'minutes'): number; +//# sourceMappingURL=dateDiffer.d.ts.map \ No newline at end of file diff --git a/dist/components/date/dateDiffer.d.ts.map b/dist/components/date/dateDiffer.d.ts.map new file mode 100644 index 0000000000..fd057d140c --- /dev/null +++ b/dist/components/date/dateDiffer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dateDiffer.d.ts","sourceRoot":"","sources":["../../../src/lib/components/date/dateDiffer.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAC7B,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,EACb,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,UAM9C"} \ No newline at end of file diff --git a/dist/components/date/dateDiffer.js b/dist/components/date/dateDiffer.js new file mode 100644 index 0000000000..15f093f2aa --- /dev/null +++ b/dist/components/date/dateDiffer.js @@ -0,0 +1,7 @@ +import { Temporal } from '@js-temporal/polyfill'; +export function getDateDaysDiff(startDate, endDate, unit) { + const diff = Temporal.Duration.from({ + milliseconds: endDate.getTime() - startDate.getTime(), + }).total({ unit: unit, relativeTo: startDate.toISOString().split('T')[0] }); + return diff > 0 ? Math.floor(diff) : Math.round(diff); +} diff --git a/dist/components/date/dateDiffer.spec.d.ts b/dist/components/date/dateDiffer.spec.d.ts new file mode 100644 index 0000000000..6ac7c30c25 --- /dev/null +++ b/dist/components/date/dateDiffer.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=dateDiffer.spec.d.ts.map \ No newline at end of file diff --git a/dist/components/date/dateDiffer.spec.d.ts.map b/dist/components/date/dateDiffer.spec.d.ts.map new file mode 100644 index 0000000000..2d93c08154 --- /dev/null +++ b/dist/components/date/dateDiffer.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dateDiffer.spec.d.ts","sourceRoot":"","sources":["../../../src/lib/components/date/dateDiffer.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/components/date/dateDiffer.spec.js b/dist/components/date/dateDiffer.spec.js new file mode 100644 index 0000000000..7fba84d0c7 --- /dev/null +++ b/dist/components/date/dateDiffer.spec.js @@ -0,0 +1,6 @@ +import { getDateDaysDiff } from './dateDiffer'; +describe('Date Differ', () => { + it('should computes the difference of days between 2 dates', () => { + expect(getDateDaysDiff(new Date('2022-10-10T20:10:39Z'), new Date('2022-11-29T15:14:39Z'), 'days')).toBe(49); + }); +}); diff --git a/dist/components/dropdown/Dropdown.component.d.ts b/dist/components/dropdown/Dropdown.component.d.ts new file mode 100644 index 0000000000..389d49b389 --- /dev/null +++ b/dist/components/dropdown/Dropdown.component.d.ts @@ -0,0 +1,19 @@ +export type Item = { + label: string; + name?: string; + selected?: boolean; + onClick: (arg0: any) => void; +}; +type Items = Array; +type Props = { + text?: string; + size?: string; + variant?: string; + title?: string; + items: Items; + icon?: JSX.Element; + caret?: boolean; +}; +declare function Dropdown({ items, text, icon, size, variant, title, caret, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Dropdown }; +//# sourceMappingURL=Dropdown.component.d.ts.map \ No newline at end of file diff --git a/dist/components/dropdown/Dropdown.component.d.ts.map b/dist/components/dropdown/Dropdown.component.d.ts.map new file mode 100644 index 0000000000..43daec3b1f --- /dev/null +++ b/dist/components/dropdown/Dropdown.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Dropdown.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/dropdown/Dropdown.component.tsx"],"names":[],"mappings":"AAgBA,MAAM,MAAM,IAAI,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC9B,CAAC;AACF,KAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,KAAK,KAAK,GAAG;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AA4DF,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,IAAa,EACb,OAA2B,EAC3B,KAAK,EACL,KAAY,EACZ,GAAG,IAAI,EACR,EAAE,KAAK,2CAgEP;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/dropdown/Dropdown.component.js b/dist/components/dropdown/Dropdown.component.js new file mode 100644 index 0000000000..358d12fd7b --- /dev/null +++ b/dist/components/dropdown/Dropdown.component.js @@ -0,0 +1,82 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { ButtonStyled, ButtonIcon, ButtonText, } from '../button/Button.component'; +import { zIndex } from '../../style/theme'; +import { spacing } from '../../spacing'; +import { fontSize } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { Icon } from '../icon/Icon.component'; +import { useSelect } from 'downshift'; +import { FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +const DropdownStyled = styled.div ` + position: relative; + user-select: none; + cursor: pointer; + .trigger { + margin: 0; + border-radius: 0; + } +`; +const DropdownMenuStyled = styled.ul ` + position: absolute; + margin: 0; + padding: 0; + top: 50px; + border: 1px solid ${getThemePropSelector('backgroundLevel1')}; + z-index: ${zIndex.dropdown}; + max-height: 200px; + min-width: 100%; + overflow: auto; + border-bottom: 0.3px solid ${getThemePropSelector('border')}; + display: ${(props) => (props.isOpen ? 'auto' : 'none')}; +`; +const DropdownMenuItemStyled = styled.li ` + display: flex; + align-items: center; + padding: ${spacing.r16}; + white-space: nowrap; + cursor: pointer; + font-size: ${fontSize.base}; + ${(props) => { + return props.isSelected + ? `background-color: ${props.theme.highlight};` + : `background-color: ${props.theme.backgroundLevel1};`; +}} + + color: ${getThemePropSelector('textPrimary')}; + border-top: 0.3px solid ${getThemePropSelector('border')}; + border-left: 0.3px solid ${getThemePropSelector('border')}; + border-right: 0.3px solid ${getThemePropSelector('border')}; + + &:hover { + background-color: ${getThemePropSelector('highlight')}; + } + &:active { + background-color: ${getThemePropSelector('highlight')}; + } +`; +const Caret = styled.span ` + margin-left: ${spacing.r16}; +`; +const Trigger = ButtonStyled.withComponent('div'); +const TriggerStyled = styled(Trigger) ` + // :focus-visible is the keyboard-only version of :focus + &:focus-visible { + ${FocusVisibleStyle} + color: ${(props) => props.theme.textPrimary}; + } +`; +function Dropdown({ items, text, icon, size = 'base', variant = 'buttonSecondary', title, caret = true, ...rest }) { + const { isOpen, getToggleButtonProps, getMenuProps, getItemProps, highlightedIndex, } = useSelect({ + items, + itemToString: (item) => (item === null || item === void 0 ? void 0 : item.label) || '', + }); + return (_jsx(DropdownStyled, { active: open, variant: variant, className: "sc-dropdown", ...rest, children: _jsxs(TriggerStyled, { variant: variant, size: size, className: "trigger", title: title, ...getToggleButtonProps(), children: [icon && (_jsx(ButtonIcon, { text: text, size: size, children: icon })), text && _jsx(ButtonText, { className: "sc-trigger-text", children: text }), caret && (_jsx(Caret, { children: _jsx(Icon, { name: "Dropdown-down" }) })), _jsx(DropdownMenuStyled, { className: "menu-item", isOpen: isOpen, ...getMenuProps(), children: items.map((item, index) => { + return (_jsx(DropdownMenuItemStyled, { className: "menu-item-label", variant: item.variant, ...item, ...getItemProps({ + item, + index, + onClick: item.onClick, + }), isSelected: index === highlightedIndex, children: item.label }, item.label)); + }) })] }) })); +} +export { Dropdown }; diff --git a/dist/components/dropzone/Dropzone.d.ts b/dist/components/dropzone/Dropzone.d.ts new file mode 100644 index 0000000000..b38033195a --- /dev/null +++ b/dist/components/dropzone/Dropzone.d.ts @@ -0,0 +1,15 @@ +import { DropzoneOptions } from 'react-dropzone'; +declare const defaultDropzoneLabels: { + doesnt_meet_our_requirements: string; + or: string; + label: string; + buttonLabel: string; + buttonAddMoreLabel: string; +}; +export declare function Dropzone({ labels, onChange, variant, ...dropzoneOptions }: DropzoneOptions & { + variant: 'inline' | 'large'; + labels?: Partial; + onChange?: (files: File[]) => void; +}): import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=Dropzone.d.ts.map \ No newline at end of file diff --git a/dist/components/dropzone/Dropzone.d.ts.map b/dist/components/dropzone/Dropzone.d.ts.map new file mode 100644 index 0000000000..e9f7b7cec0 --- /dev/null +++ b/dist/components/dropzone/Dropzone.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Dropzone.d.ts","sourceRoot":"","sources":["../../../src/lib/components/dropzone/Dropzone.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAe,MAAM,gBAAgB,CAAC;AAoC9D,QAAA,MAAM,qBAAqB;;;;;;CAM1B,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,QAAQ,EACR,OAAO,EACP,GAAG,eAAe,EACnB,EAAE,eAAe,GAAG;IACnB,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,qBAAqB,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;CACpC,2CA8HA"} \ No newline at end of file diff --git a/dist/components/dropzone/Dropzone.js b/dist/components/dropzone/Dropzone.js new file mode 100644 index 0000000000..fdc36eed36 --- /dev/null +++ b/dist/components/dropzone/Dropzone.js @@ -0,0 +1,79 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { useState } from 'react'; +import { useDropzone } from 'react-dropzone'; +import styled from 'styled-components'; +import { spacing, Stack, Wrap } from '../../spacing'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +import { Text } from '../text/Text.component'; +const DropzoneContainer = styled.div ` + padding: ${spacing.r24}; + border: ${spacing.f2} dashed + ${(props) => !props.isDragActive + ? props.theme.textSecondary + : props.theme.selectedActive}; + box-sizing: border-box; + display: flex; + ${(props) => (props.variant === 'large' ? `text-align: center;` : ``)} +`; +const FileList = styled.div ` + max-height: 100px; + overflow-y: auto; + flex: 1; + width: 100%; +`; +const FileListItem = styled(Wrap) ` + align-items: baseline; + &:hover { + background: ${(props) => props.theme.selectedActive}; + } +`; +const defaultDropzoneLabels = { + doesnt_meet_our_requirements: "doesn't meet our requirements", + or: 'OR', + label: 'Drag and drop files and folders here', + buttonLabel: 'Add files', + buttonAddMoreLabel: 'Add more files', +}; +export function Dropzone({ labels, onChange, variant, ...dropzoneOptions }) { + labels = { ...defaultDropzoneLabels, ...labels }; + const [acceptedFiles, setAcceptedFiles] = useState([]); + const { getRootProps, getInputProps, isDragActive, fileRejections } = useDropzone({ + ...dropzoneOptions, + onDrop: (acceptedFiles, rejectedFiles, e) => { + const { multiple } = dropzoneOptions; + setAcceptedFiles((alreadyAcceptedFiles) => { + const singleFileAlreadyHasFile = !multiple && alreadyAcceptedFiles.length === 1; + const newAcceptedFiles = singleFileAlreadyHasFile + ? alreadyAcceptedFiles + : [...alreadyAcceptedFiles, ...acceptedFiles]; + if (onChange) { + onChange(newAcceptedFiles); + } + return newAcceptedFiles; + }); + if (dropzoneOptions.onDrop) { + dropzoneOptions.onDrop(acceptedFiles, rejectedFiles, e); + } + }, + }); + const { multiple } = dropzoneOptions; + const { onClick, ...rootProps } = getRootProps(); + const removeFile = (fileIndex) => { + setAcceptedFiles((alreadyAcceptedFiles) => { + const newAcceptedFiles = [...alreadyAcceptedFiles]; + newAcceptedFiles.splice(fileIndex, 1); + if (onChange) { + onChange(newAcceptedFiles); + } + return newAcceptedFiles; + }); + }; + return (_jsxs(Stack, { direction: "vertical", children: [_jsxs(DropzoneContainer, { ...rootProps, isDragActive: isDragActive, variant: variant, children: [_jsx("input", { ...getInputProps() }), _jsx("div", { style: { flex: '1' }, children: !multiple && acceptedFiles.length === 1 ? (_jsxs(FileListItem, { children: [_jsx(Text, { children: acceptedFiles[0].name }), _jsx(Button, { icon: _jsx(Icon, { name: "Close" }), tooltip: { overlay: 'Remove' }, "aria-label": `Remove ${acceptedFiles[0].name}`, type: "button", onClick: () => { + removeFile(0); + } })] })) : multiple && acceptedFiles.length > 0 ? (_jsxs(Stack, { direction: "vertical", children: [_jsx(Button, { icon: variant === 'large' ? _jsx(Icon, { name: "Create-add" }) : undefined, variant: "secondary", type: "button", label: labels.buttonAddMoreLabel, onClick: onClick }), _jsx(FileList, { children: acceptedFiles.map((file, index) => (_jsxs(FileListItem, { children: [_jsx(Text, { children: file.name }), _jsx(Button, { icon: _jsx(Icon, { name: "Close" }), tooltip: { overlay: 'Remove' }, "aria-label": `Remove ${file.name}`, type: "button", onClick: () => { + removeFile(index); + } })] }, index))) })] })) : (_jsxs(Stack, { direction: variant === 'large' ? 'vertical' : 'horizontal', gap: 'f16', children: [_jsx(Text, { children: _jsx(Icon, { name: "Upload", size: "3x" }) }), _jsx(Text, { children: labels.label }), variant === 'large' && _jsx(Text, { children: labels.or }), _jsx(Button, { icon: variant === 'large' ? _jsx(Icon, { name: "Create-add" }) : undefined, label: labels.buttonLabel, variant: "secondary", type: "button", onClick: onClick })] })) })] }), _jsx(Text, { variant: "Smaller", isEmphazed: true, color: "statusCritical", children: fileRejections.length > 0 ? (fileRejections.map((rejection) => rejection.file.name) + + ' ' + + labels.doesnt_meet_our_requirements) : (_jsx(_Fragment, { children: "\u00A0" })) })] })); +} diff --git a/dist/components/emptystate/Emptystate.component.d.ts b/dist/components/emptystate/Emptystate.component.d.ts new file mode 100644 index 0000000000..aef67c9e1c --- /dev/null +++ b/dist/components/emptystate/Emptystate.component.d.ts @@ -0,0 +1,21 @@ +import { IconName } from '../icon/Icon.component'; +import { CoreUITheme } from '../../style/theme'; +export type Props = { + listedResource: { + singular: string; + plural: string; + }; + icon: IconName; + link?: string; + backgroundColor?: keyof CoreUITheme; + /** + * The resource to create before browsing the listed resource + * Only used when resource to create is different from listed resource + */ + resourceToCreate?: string; +}; +export declare const EmptyStateRow: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const ActionWrapper: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +declare function EmptyState(props: Props): import("react/jsx-runtime").JSX.Element; +export { EmptyState }; +//# sourceMappingURL=Emptystate.component.d.ts.map \ No newline at end of file diff --git a/dist/components/emptystate/Emptystate.component.d.ts.map b/dist/components/emptystate/Emptystate.component.d.ts.map new file mode 100644 index 0000000000..203cdb4d40 --- /dev/null +++ b/dist/components/emptystate/Emptystate.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Emptystate.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/emptystate/Emptystate.component.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAQ,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,MAAM,KAAK,GAAG;IAClB,cAAc,EAAE;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,WAAW,CAAC;IACpC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAgBF,eAAO,MAAM,aAAa,yGAIzB,CAAC;AACF,eAAO,MAAM,aAAa,yGAGzB,CAAC;AAEF,iBAAS,UAAU,CAAC,KAAK,EAAE,KAAK,2CAmC/B;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/emptystate/Emptystate.component.js b/dist/components/emptystate/Emptystate.component.js new file mode 100644 index 0000000000..41e5358949 --- /dev/null +++ b/dist/components/emptystate/Emptystate.component.js @@ -0,0 +1,39 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +import { LargeText } from '../text/Text.component'; +import { useHistory } from 'react-router'; +const EmptystateContainer = styled.div ` + ${(props) => { + const { theme, backgroundColor } = props; + return css ` + color: ${theme.textSecondary}; + background-color: ${backgroundColor + ? theme[backgroundColor] + : 'transparent'}; + `; +}} + display: flex; + flex-direction: column; + width: 100%; + padding-top: 10%; +`; +export const EmptyStateRow = styled.div ` + display: flex; + justify-content: space-around; + margin-bottom: ${spacing.r24}; +`; +export const ActionWrapper = styled.div ` + display: flex; + justify-content: space-around; +`; +function EmptyState(props) { + const { icon, listedResource, link, resourceToCreate, backgroundColor } = props; + const history = useHistory(); + return (_jsxs(EmptystateContainer, { className: "sc-emptystate", backgroundColor: backgroundColor, children: [_jsx(EmptyStateRow, { children: _jsx(Icon, { name: icon, color: "infoPrimary", size: "5x", withWrapper: true }) }), _jsx(EmptyStateRow, { children: _jsx(LargeText, { children: `A list of ${listedResource.plural} will appear here.` }) }), _jsx(EmptyStateRow, { children: _jsx(LargeText, { children: !resourceToCreate + ? `There are no ${listedResource.plural} created yet, let's create your first ${listedResource.singular}.` + : `Before browsing your ${listedResource.plural}, create your first ${resourceToCreate}.` }) }), link && (_jsx(ActionWrapper, { children: _jsx(Button, { label: `Create ${resourceToCreate || listedResource.singular}`, icon: _jsx(Icon, { name: "Create-add" }), type: "button", variant: "primary", onClick: () => history.push(link) }) }))] })); +} +export { EmptyState }; diff --git a/dist/components/emptytable/Emptytable.component.d.ts b/dist/components/emptytable/Emptytable.component.d.ts new file mode 100644 index 0000000000..2a5ad2e2d8 --- /dev/null +++ b/dist/components/emptytable/Emptytable.component.d.ts @@ -0,0 +1,8 @@ +import * as React from 'react'; +type Props = { + children: Node | React.ReactNode; + useDiv?: boolean; +}; +declare function EmptyTable(props: Props): import("react/jsx-runtime").JSX.Element; +export { EmptyTable }; +//# sourceMappingURL=Emptytable.component.d.ts.map \ No newline at end of file diff --git a/dist/components/emptytable/Emptytable.component.d.ts.map b/dist/components/emptytable/Emptytable.component.d.ts.map new file mode 100644 index 0000000000..1c9890342d --- /dev/null +++ b/dist/components/emptytable/Emptytable.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Emptytable.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/emptytable/Emptytable.component.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAuDF,iBAAS,UAAU,CAAC,KAAK,EAAE,KAAK,2CAY/B;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/emptytable/Emptytable.component.js b/dist/components/emptytable/Emptytable.component.js new file mode 100644 index 0000000000..795c43e7e5 --- /dev/null +++ b/dist/components/emptytable/Emptytable.component.js @@ -0,0 +1,62 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +const EmptytableContainer = styled.tr ` + width: 100%; + padding: ${spacing.r20}; + box-sizing: border-box; + display: table; + table-layout: fixed; + + ${(props) => { + const brand = props.theme; + return css ` + background: ${brand.backgroundLevel2}; + border-top: 1px solid ${brand.border}; + `; +}} +`; +const EmptytableContainerDiv = styled.div ` + width: 100%; + padding: ${spacing.r20}; + box-sizing: border-box; + display: table; + table-layout: fixed; + + ${(props) => { + const brand = props.theme; + return css ` + background: ${brand.backgroundLevel2}; + border-top: 1px solid ${brand.border}; + `; +}} +`; +// Using !important as the only way to prioritize this over the general tr td styling that may be defined in the apps +const EmptytableContent = styled.td ` + text-align: center !important; + border: none !important; + ${(props) => { + const brand = props.theme; + return css ` + background: ${brand.backgroundLevel2}; + color: ${brand.textSecondary}; + `; +}} +`; +const EmptytableContentDiv = styled.div ` + text-align: center !important; + border: none !important; + ${(props) => { + const brand = props.theme; + return css ` + background: ${brand.backgroundLevel2}; + color: ${brand.textSecondary}; + `; +}} +`; +function EmptyTable(props) { + if (props.useDiv) + return (_jsx(EmptytableContainerDiv, { className: "sc-emptytable", children: _jsx(EmptytableContentDiv, { children: props.children }) })); + return (_jsx(EmptytableContainer, { className: "sc-emptytable", children: _jsx(EmptytableContent, { children: props.children }) })); +} +export { EmptyTable }; diff --git a/dist/components/error-pages/ErrorPage401.component.d.ts b/dist/components/error-pages/ErrorPage401.component.d.ts new file mode 100644 index 0000000000..36f2c12dbd --- /dev/null +++ b/dist/components/error-pages/ErrorPage401.component.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; +type Props = { + supportLink?: string; + locale?: string; + onReturnHomeClick?: (event: React.MouseEvent) => void; +}; +declare function ErrorPage401({ supportLink, locale, onReturnHomeClick, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { ErrorPage401 }; +//# sourceMappingURL=ErrorPage401.component.d.ts.map \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPage401.component.d.ts.map b/dist/components/error-pages/ErrorPage401.component.d.ts.map new file mode 100644 index 0000000000..f9f1d531f1 --- /dev/null +++ b/dist/components/error-pages/ErrorPage401.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ErrorPage401.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/error-pages/ErrorPage401.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA2B1B,KAAK,KAAK,GAAG;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CAC1E,CAAC;AAEF,iBAAS,YAAY,CAAC,EACpB,WAAuB,EACvB,MAAa,EACb,iBAAiB,EACjB,GAAG,IAAI,EACR,EAAE,KAAK,2CAoCP;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPage401.component.js b/dist/components/error-pages/ErrorPage401.component.js new file mode 100644 index 0000000000..eeeec69d73 --- /dev/null +++ b/dist/components/error-pages/ErrorPage401.component.js @@ -0,0 +1,28 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { ErrorPageContainer, Row, Title, Description, DescriptionContent, Link, } from './ErrorPageStyle'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +const translations = { + en: { + unexpected_error: 'Not authorized', + error_desc: `You don't have permission to view this page using the credentials you have supplied.`, + may_also_contact: 'You can contact ', + to_report_issue: ' to report this issue.', + return_home: 'Return Home', + }, + fr: { + unexpected_error: `Accès refusé`, + error_desc: `Les identifiants fournis ne vous permettent pas de consulter cette page.`, + may_also_contact: 'Vous pouvez contacter le ', + to_report_issue: ' pour signaler le problème.', + return_home: "Retour à l'accueil", + }, +}; +function ErrorPage401({ supportLink = undefined, locale = 'en', onReturnHomeClick, ...rest }) { + if (!translations[locale]) + locale = 'en'; + // Ensure the locale formatting is consistent + locale = locale.toLowerCase(); + return (_jsxs(ErrorPageContainer, { className: "sc-error-page401", ...rest, children: [_jsxs(Row, { children: [_jsx(Icon, { name: "Exclamation-triangle", size: "2x", color: "statusWarning" }), _jsx(Title, { children: translations[locale].unexpected_error })] }), _jsx(Row, { children: _jsxs(Description, { children: [_jsx(DescriptionContent, { children: translations[locale].error_desc }), supportLink && (_jsxs(DescriptionContent, { children: [translations[locale].may_also_contact, _jsxs(Link, { href: supportLink, children: ["support ", _jsx(Icon, { name: "External-link" })] }), translations[locale].to_report_issue] }))] }) }), onReturnHomeClick && (_jsx(Button, { label: translations[locale].return_home, variant: "secondary", onClick: onReturnHomeClick }))] })); +} +export { ErrorPage401 }; diff --git a/dist/components/error-pages/ErrorPage404.component.d.ts b/dist/components/error-pages/ErrorPage404.component.d.ts new file mode 100644 index 0000000000..60db6c7cae --- /dev/null +++ b/dist/components/error-pages/ErrorPage404.component.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +type Props = { + locale?: string; + onReturnHomeClick?: (event: React.MouseEvent) => void; +}; +declare function ErrorPage404({ locale, onReturnHomeClick, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { ErrorPage404 }; +//# sourceMappingURL=ErrorPage404.component.d.ts.map \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPage404.component.d.ts.map b/dist/components/error-pages/ErrorPage404.component.d.ts.map new file mode 100644 index 0000000000..6bf0555f4f --- /dev/null +++ b/dist/components/error-pages/ErrorPage404.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ErrorPage404.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/error-pages/ErrorPage404.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA2B1B,KAAK,KAAK,GAAG;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CAC1E,CAAC;AAEF,iBAAS,YAAY,CAAC,EAAE,MAAa,EAAE,iBAAiB,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CA6BzE;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPage404.component.js b/dist/components/error-pages/ErrorPage404.component.js new file mode 100644 index 0000000000..a604062132 --- /dev/null +++ b/dist/components/error-pages/ErrorPage404.component.js @@ -0,0 +1,26 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { ErrorPageContainer, Row, Title, Description, DescriptionContent, } from './ErrorPageStyle'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +const translations = { + en: { + not_exist: 'Error: this page does not exist', + error_desc: 'It might be the wrong address or the page has moved.', + should_do: 'You might check the url, or contact your admin if the error remains.', + return_home: 'Return Home', + }, + fr: { + not_exist: "Erreur: cette page n'existe pas", + error_desc: 'Il se peut que ce soit une mauvaise adresse ou que la page ait été déplacée.', + should_do: "Vous pouvez vérifier l'url, ou contacter votre administrateur si l'erreur persiste.", + return_home: "Retour à l'accueil", + }, +}; +function ErrorPage404({ locale = 'en', onReturnHomeClick, ...rest }) { + if (!translations[locale]) + locale = 'en'; + // Ensure the locale formatting is consistent + locale = locale.toLowerCase(); + return (_jsxs(ErrorPageContainer, { className: "sc-error-page404", ...rest, children: [_jsxs(Row, { children: [_jsx(Icon, { name: "Exclamation-triangle", size: "2x", color: "statusWarning" }), _jsx(Title, { children: translations[locale].not_exist })] }), _jsx(Row, { children: _jsxs(Description, { children: [_jsx(DescriptionContent, { children: translations[locale].error_desc }), _jsx(DescriptionContent, { children: translations[locale].should_do })] }) }), onReturnHomeClick && (_jsx(Button, { label: translations[locale].return_home, variant: "secondary", onClick: onReturnHomeClick }))] })); +} +export { ErrorPage404 }; diff --git a/dist/components/error-pages/ErrorPage500.component.d.ts b/dist/components/error-pages/ErrorPage500.component.d.ts new file mode 100644 index 0000000000..5d945fe000 --- /dev/null +++ b/dist/components/error-pages/ErrorPage500.component.d.ts @@ -0,0 +1,13 @@ +import React from 'react'; +type Props = { + supportLink?: string; + locale?: string; + onReturnHomeClick?: (event: React.MouseEvent) => void; + errorMessage?: { + en: string; + fr: string; + }; +}; +declare function ErrorPage500({ supportLink, locale, onReturnHomeClick, errorMessage, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { ErrorPage500 }; +//# sourceMappingURL=ErrorPage500.component.d.ts.map \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPage500.component.d.ts.map b/dist/components/error-pages/ErrorPage500.component.d.ts.map new file mode 100644 index 0000000000..0fa420f9dd --- /dev/null +++ b/dist/components/error-pages/ErrorPage500.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ErrorPage500.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/error-pages/ErrorPage500.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgC1B,KAAK,KAAK,GAAG;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACzE,YAAY,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,CAAC;AAEF,iBAAS,YAAY,CAAC,EACpB,WAAuB,EACvB,MAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,GAAG,IAAI,EACR,EAAE,KAAK,2CAwCP;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPage500.component.js b/dist/components/error-pages/ErrorPage500.component.js new file mode 100644 index 0000000000..a8e6555aa7 --- /dev/null +++ b/dist/components/error-pages/ErrorPage500.component.js @@ -0,0 +1,32 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { ErrorPageContainer, Row, Title, Description, DescriptionContent, Link, } from './ErrorPageStyle'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +const translations = { + en: { + unexpected_error: 'Unexpected Error', + error_desc: 'An error occured and your request cannot be completed.', + should_do: 'You might check the url, or contact your admin if the error remains.', + return_home: 'Return Home', + may_also_contact: 'You may also contact ', + to_report_issue: ' to report this issue.', + }, + fr: { + unexpected_error: 'Erreur inattendue', + error_desc: "Une erreur s'est produite et votre demande ne peut être complétée.", + should_do: "Vous pouvez vérifier l'url, ou contacter votre administrateur si l'erreur persiste.", + return_home: "Retour à l'accueil", + may_also_contact: 'Vous pouvez également contacter le ', + to_report_issue: ' pour signaler le problème.', + }, +}; +function ErrorPage500({ supportLink = undefined, locale = 'en', onReturnHomeClick, errorMessage, ...rest }) { + if (!translations[locale]) + locale = 'en'; + // Ensure the locale formatting is consistent + locale = locale.toLowerCase(); + return (_jsxs(ErrorPageContainer, { className: "sc-error-page500", ...rest, children: [_jsxs(Row, { children: [_jsx(Icon, { name: "Exclamation-triangle", size: "2x", color: "statusWarning" }), _jsx(Title, { children: translations[locale].unexpected_error })] }), _jsx(Row, { children: _jsxs(Description, { children: [_jsx(DescriptionContent, { children: errorMessage + ? errorMessage[locale] + : translations[locale].error_desc }), _jsx(DescriptionContent, { children: translations[locale].should_do }), supportLink && (_jsxs(DescriptionContent, { children: [translations[locale].may_also_contact, _jsxs(Link, { href: supportLink, children: ["support ", _jsx(Icon, { name: "External-link" })] }), translations[locale].to_report_issue] }))] }) }), onReturnHomeClick && (_jsx(Button, { label: translations[locale].return_home, variant: "secondary", onClick: onReturnHomeClick }))] })); +} +export { ErrorPage500 }; diff --git a/dist/components/error-pages/ErrorPageAuth.component.d.ts b/dist/components/error-pages/ErrorPageAuth.component.d.ts new file mode 100644 index 0000000000..c3044a361f --- /dev/null +++ b/dist/components/error-pages/ErrorPageAuth.component.d.ts @@ -0,0 +1,7 @@ +type Props = { + supportLink?: string; + locale?: string; +}; +declare function ErrorPageAuth({ supportLink, locale, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { ErrorPageAuth }; +//# sourceMappingURL=ErrorPageAuth.component.d.ts.map \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPageAuth.component.d.ts.map b/dist/components/error-pages/ErrorPageAuth.component.d.ts.map new file mode 100644 index 0000000000..390d575ad2 --- /dev/null +++ b/dist/components/error-pages/ErrorPageAuth.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ErrorPageAuth.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/error-pages/ErrorPageAuth.component.tsx"],"names":[],"mappings":"AA2BA,KAAK,KAAK,GAAG;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,iBAAS,aAAa,CAAC,EACrB,WAAuB,EACvB,MAAa,EACb,GAAG,IAAI,EACR,EAAE,KAAK,2CA+BP;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPageAuth.component.js b/dist/components/error-pages/ErrorPageAuth.component.js new file mode 100644 index 0000000000..292daaa8b6 --- /dev/null +++ b/dist/components/error-pages/ErrorPageAuth.component.js @@ -0,0 +1,27 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { Icon } from '../icon/Icon.component'; +import { ErrorPageContainer, Row, Title, Description, DescriptionContent, Link, } from './ErrorPageStyle'; +const translations = { + en: { + unexpected_error: 'Authenticating...', + error_desc: 'The authentication is in progress.', + should_do: 'If this message persist please try refreshing your page.', + may_also_contact: 'You may also contact ', + to_report_issue: ' to report this issue.', + }, + fr: { + unexpected_error: 'Authentification', + error_desc: 'Authentification en cours.', + should_do: "Si ce message persiste, vous pouvez essayer d'actualiser cette page.", + may_also_contact: 'Vous pouvez également contacter le ', + to_report_issue: ' pour signaler le problème.', + }, +}; +function ErrorPageAuth({ supportLink = undefined, locale = 'en', ...rest }) { + if (!translations[locale]) + locale = 'en'; + // Ensure the locale formatting is consistent + locale = locale.toLowerCase(); + return (_jsxs(ErrorPageContainer, { className: "sc-error-pageauth", ...rest, children: [_jsxs(Row, { children: [_jsx(Icon, { name: "Info-circle", size: "2x", color: "textPrimary" }), _jsx(Title, { children: translations[locale].unexpected_error })] }), _jsx(Row, { children: _jsxs(Description, { children: [_jsx(DescriptionContent, { children: translations[locale].error_desc }), _jsx(DescriptionContent, { children: translations[locale].should_do }), supportLink && (_jsxs(DescriptionContent, { children: [translations[locale].may_also_contact, _jsxs(Link, { href: supportLink, children: ["support ", _jsx(Icon, { name: "External-link" })] }), translations[locale].to_report_issue] }))] }) })] })); +} +export { ErrorPageAuth }; diff --git a/dist/components/error-pages/ErrorPageStyle.d.ts b/dist/components/error-pages/ErrorPageStyle.d.ts new file mode 100644 index 0000000000..89d6987034 --- /dev/null +++ b/dist/components/error-pages/ErrorPageStyle.d.ts @@ -0,0 +1,7 @@ +export declare const ErrorPageContainer: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const Title: import("styled-components").StyledComponent<"h2", import("styled-components").DefaultTheme, {}, never>; +export declare const Description: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const DescriptionContent: import("styled-components").StyledComponent<"p", import("styled-components").DefaultTheme, {}, never>; +export declare const Row: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const Link: import("styled-components").StyledComponent<"a", import("styled-components").DefaultTheme, {}, never>; +//# sourceMappingURL=ErrorPageStyle.d.ts.map \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPageStyle.d.ts.map b/dist/components/error-pages/ErrorPageStyle.d.ts.map new file mode 100644 index 0000000000..864bfd619c --- /dev/null +++ b/dist/components/error-pages/ErrorPageStyle.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ErrorPageStyle.d.ts","sourceRoot":"","sources":["../../../src/lib/components/error-pages/ErrorPageStyle.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB,yGAO9B,CAAC;AACF,eAAO,MAAM,KAAK,wGAIjB,CAAC;AACF,eAAO,MAAM,WAAW,yGAKvB,CAAC;AACF,eAAO,MAAM,kBAAkB,uGAG9B,CAAC;AACF,eAAO,MAAM,GAAG,yGAGf,CAAC;AACF,eAAO,MAAM,IAAI,uGAGhB,CAAC"} \ No newline at end of file diff --git a/dist/components/error-pages/ErrorPageStyle.js b/dist/components/error-pages/ErrorPageStyle.js new file mode 100644 index 0000000000..d130d901a0 --- /dev/null +++ b/dist/components/error-pages/ErrorPageStyle.js @@ -0,0 +1,34 @@ +import styled from 'styled-components'; +import { spacing, fontSize } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +export const ErrorPageContainer = styled.div ` + background-color: ${getThemePropSelector('backgroundLevel1')}; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; +`; +export const Title = styled.h2 ` + color: ${getThemePropSelector('textPrimary')}; + margin: 0; + margin-left: ${spacing.sp20}; +`; +export const Description = styled.div ` + color: ${getThemePropSelector('textPrimary')}; + font-size: ${fontSize.larger}; + text-align: center; + padding: ${spacing.sp24}; +`; +export const DescriptionContent = styled.p ` + margin: 0; + padding: ${spacing.sp4}; +`; +export const Row = styled.div ` + display: flex; + align-items: center; +`; +export const Link = styled.a ` + color: ${getThemePropSelector('textLink')}; + text-decoration: none; +`; diff --git a/dist/components/form/Form.component.d.ts b/dist/components/form/Form.component.d.ts new file mode 100644 index 0000000000..2fa7ae5940 --- /dev/null +++ b/dist/components/form/Form.component.d.ts @@ -0,0 +1,61 @@ +import React, { FormHTMLAttributes, ReactElement, ReactNode } from 'react'; +import { IconName } from '../icon/Icon.component'; +declare const DESCRIPTION_PREFIX = "describe-"; +declare const LABEL_PREFIX = "label-"; +type FormProps = Omit, 'noValidate' | 'formNoValidate'> & { + children: ReactNode | ReactNode[]; + requireMode?: 'all' | 'partial'; + leftActions?: ReactNode; + rightActions?: ReactNode; + banner?: ReactNode; +}; +type PageFormProps = { + layout: { + kind: 'page'; + title: string; + subTitle?: string; + icon?: IconName; + }; +} & FormProps; +type TabFormProps = { + layout: { + kind: 'tab'; + }; +} & FormProps; +type ContentProps = { + helper: string; + error: string; +}; +type FormGroupProps = { + label: string; + id: string; + content: ReactElement; + direction?: 'vertical' | 'horizontal'; + labelHelpTooltip?: ReactNode; + help?: string; + error?: string; + required?: boolean; + helpErrorPosition?: 'right' | 'bottom'; + disabled?: boolean; +}; +declare const FormGroup: ({ direction, label, id, labelHelpTooltip, content, help, error, required, helpErrorPosition, disabled, }: FormGroupProps) => import("react/jsx-runtime").JSX.Element; +type FormSectionProps = { + children: ReactElement | ReactElement[]; + title?: { + name: string; + icon?: IconName; + helpTooltip?: string; + }; + forceLabelWidth?: number; + rightActions?: ReactNode; +}; +declare const FormSection: ({ children, title, forceLabelWidth, rightActions, }: FormSectionProps) => import("react/jsx-runtime").JSX.Element; +declare const Form: React.ForwardRefExoticComponent<(PageFormProps | TabFormProps) & React.RefAttributes>; +declare const useFieldContext: () => { + isContextAvailable: boolean; + error?: string; + disabled?: boolean; + required?: boolean; +}; +export { Form, FormSection, FormGroup, useFieldContext, DESCRIPTION_PREFIX, LABEL_PREFIX, }; +//# sourceMappingURL=Form.component.d.ts.map \ No newline at end of file diff --git a/dist/components/form/Form.component.d.ts.map b/dist/components/form/Form.component.d.ts.map new file mode 100644 index 0000000000..c92381546a --- /dev/null +++ b/dist/components/form/Form.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Form.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/form/Form.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAGZ,kBAAkB,EAGlB,YAAY,EACZ,SAAS,EAKV,MAAM,OAAO,CAAC;AAKf,OAAO,EAAQ,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAKxD,QAAA,MAAM,kBAAkB,cAAc,CAAC;AACvC,QAAA,MAAM,YAAY,WAAW,CAAC;AAG9B,KAAK,SAAS,GAAG,IAAI,CACnB,kBAAkB,CAAC,eAAe,CAAC,EACnC,YAAY,GAAG,gBAAgB,CAChC,GAAG;IACF,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAChC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,QAAQ,CAAC;KACjB,CAAC;CACH,GAAG,SAAS,CAAC;AACd,KAAK,YAAY,GAAG;IAAE,MAAM,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAA;CAAE,GAAG,SAAS,CAAC;AAyD5D,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,QAAA,MAAM,SAAS,6GAWZ,cAAc,4CAsGhB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IACxE,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B,CAAC;AAEF,QAAA,MAAM,WAAW,wDAKd,gBAAgB,4CAmClB,CAAC;AAgGF,QAAA,MAAM,IAAI,wGAYT,CAAC;AASF,QAAA,MAAM,eAAe;;YANX,MAAM;eACH,OAAO;eACP,OAAO;CAWnB,CAAC;AAEF,OAAO,EACL,IAAI,EACJ,WAAW,EACX,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,YAAY,GACb,CAAC"} \ No newline at end of file diff --git a/dist/components/form/Form.component.js b/dist/components/form/Form.component.js new file mode 100644 index 0000000000..8cfc83553c --- /dev/null +++ b/dist/components/form/Form.component.js @@ -0,0 +1,115 @@ +import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime"; +import { Children, createContext, forwardRef, isValidElement, useContext, useEffect, useRef, useState, } from 'react'; +import styled from 'styled-components'; +import { spacing, Stack, Wrap } from '../../spacing'; +import { convertRemToPixels } from '../../utils'; +import { Box } from '../box/Box'; +import { Icon } from '../icon/Icon.component'; +import { IconHelp } from '../IconHelper'; +import { ScrollbarWrapper } from '../scrollbarwrapper/ScrollbarWrapper.component'; +import { Text } from '../text/Text.component'; +const DESCRIPTION_PREFIX = 'describe-'; +const LABEL_PREFIX = 'label-'; +const maxWidthTooltip = { maxWidth: '20rem' }; +const StyledForm = styled.form ` + display: flex; + flex-direction: column; + align-items: stretch; + height: 100%; + background-color: ${(props) => props.layout.kind === 'page' && props.theme.backgroundLevel4}; +`; +const BasicPageLayout = styled.div ` + margin: 0 auto; + ${(props) => props.layoutKind === 'page' + ? ` + width: 45rem; + padding-right: ${spacing.f16}; + ` + : ` + width: 100%; + padding-bottom: ${spacing.r24};`} +`; +const FixedHeader = styled(BasicPageLayout) ` + ${(props) => props.layoutKind === 'page' + ? ` + border-bottom: 1px solid ${props.theme.border}; + ` + : ``} +`; +const FixedFooter = styled(BasicPageLayout) ` + border-top: 1px solid ${(props) => props.theme.border}; +`; +const PaddedContent = styled.div ` + padding: ${spacing.f16} 0 ${spacing.f16} ${spacing.f16}; +`; +const PaddedForHeaderAndFooterContent = styled.div ` + padding: ${spacing.f16}; +`; +const ScrollArea = styled(BasicPageLayout) ` + flex-grow: 1; + align-self: stretch; + overflow-y: auto; +`; +const LabelContext = createContext(null); +const RequireModeContext = createContext('partial'); +const FormGroup = ({ direction = 'horizontal', label, id, labelHelpTooltip, content, help, error, required, helpErrorPosition = 'right', disabled, }) => { + const ctxt = useContext(LabelContext); + if (!ctxt) { + //intentionaly breaking rules of hooks here + throw new Error('FormGroup cannot be used outside of Form'); + } + const { maxLabelWidth, setMaxLabelWidth } = ctxt; + const requireMode = useContext(RequireModeContext); + const labelRef = useRef(null); + useEffect(() => { + if (labelRef.current) { + const width = labelRef.current.getBoundingClientRect().width; + setMaxLabelWidth((currentMaxLabelWidth) => { + const additionalWdth = labelHelpTooltip ? convertRemToPixels(2) : 0; + if (width + additionalWdth > currentMaxLabelWidth) { + return width + additionalWdth; + } + return currentMaxLabelWidth; + }); + } + }, [labelRef]); + const value = { + disabled: disabled || false, + error: error || undefined, + }; + return (_jsx(FieldContext.Provider, { value: value, children: _jsxs(Box, { display: "flex", flexDirection: direction === 'horizontal' ? 'row' : 'column', alignItems: "baseline", gap: direction === 'horizontal' ? spacing['r32'] : spacing['r4'], children: [_jsx("div", { style: { + width: maxLabelWidth === 0 ? 'max-content' : `${maxLabelWidth}px`, + flex: 'none', + }, children: _jsxs(Stack, { children: [_jsx("label", { htmlFor: id, id: `${LABEL_PREFIX}${id}`, ref: labelRef, style: { opacity: disabled ? 0.5 : 1 }, children: _jsxs(Text, { children: [label, requireMode !== 'all' && required && ' *', requireMode === 'all' && !required && ' (optional)'] }) }), labelHelpTooltip && (_jsx(IconHelp, { tooltipMessage: labelHelpTooltip, overlayStyle: maxWidthTooltip }))] }) }), _jsxs(Stack, { direction: helpErrorPosition === 'right' ? 'horizontal' : 'vertical', gap: helpErrorPosition === 'right' ? 'r8' : 'r4', children: [content, error ? (_jsx(Text, { variant: "Smaller", color: "statusCritical", isEmphazed: true, id: `${DESCRIPTION_PREFIX}${id}`, children: error })) : help ? (_jsx("div", { style: { + opacity: disabled ? 0.5 : 1, + }, children: _jsx(Text, { variant: "Smaller", color: "textSecondary", isEmphazed: true, id: `${DESCRIPTION_PREFIX}${id}`, children: help }) })) : (_jsx(Text, { variant: "Smaller", isEmphazed: true, children: "\u00A0" }))] })] }) })); +}; +const FormSection = ({ children, title, forceLabelWidth, rightActions, }) => { + const [maxLabelWidth, setMaxLabelWidth] = useState(forceLabelWidth || 0); + //If all the formgroup are not required, add `(optional)` next to form section title. + const groupNotOptional = Children.toArray(children).find((child) => isValidElement(child) ? child.props.required === true : false); + return (_jsx(LabelContext.Provider, { value: { maxLabelWidth, setMaxLabelWidth }, children: _jsxs(Stack, { direction: "vertical", gap: "r12", children: [title && (_jsxs(Wrap, { children: [_jsxs(Stack, { direction: "horizontal", gap: "r8", children: [title.icon && _jsx(Icon, { name: title.icon, color: "textPrimary" }), _jsx(Text, { isEmphazed: true, children: groupNotOptional + ? `${title.name}` + : `${title.name} (optional)` }), title.helpTooltip && (_jsx(IconHelp, { tooltipMessage: title.helpTooltip, overlayStyle: maxWidthTooltip }))] }), _jsx("div", { children: rightActions })] })), children] }) })); +}; +const PageForm = forwardRef(({ layout, leftActions, rightActions, children, banner, ...formProps }, ref) => { + const requireMode = useContext(RequireModeContext); + return (_jsx(ScrollbarWrapper, { children: _jsxs(StyledForm, { ...formProps, noValidate: true, ref: ref, layout: layout, children: [_jsx(FixedHeader, { layoutKind: "page", children: _jsx(PaddedForHeaderAndFooterContent, { children: _jsxs(Wrap, { children: [_jsxs(Stack, { direction: "vertical", children: [_jsxs(Text, { variant: "Larger", children: [layout.icon && (_jsx(Icon, { name: layout.icon, color: "textSecondary" })), ' ', layout.title] }), layout.subTitle && (_jsx(Text, { variant: "Large", isEmphazed: true, children: layout.subTitle }))] }), requireMode === 'partial' && (_jsx(Text, { color: "textSecondary", variant: "Smaller", style: { alignSelf: 'flex-end' }, isGentleEmphazed: true, children: "* are required fields" }))] }) }) }), _jsx(ScrollArea, { layoutKind: "page", children: _jsxs(PaddedContent, { children: [_jsx("div", { style: { + paddingBottom: `${spacing.r16}`, + }, children: banner }), _jsx(Stack, { direction: "vertical", withSeparators: true, gap: "r24", children: Children.toArray(children) })] }) }), _jsx(FixedFooter, { layoutKind: "page", children: _jsx(PaddedForHeaderAndFooterContent, { children: _jsxs(Wrap, { children: [_jsx("div", { children: leftActions }), _jsx("div", { children: rightActions })] }) }) })] }) })); +}); +const TabForm = forwardRef(({ leftActions, rightActions, children, banner, ...formProps }, ref) => { + return (_jsx(ScrollbarWrapper, { children: _jsxs(StyledForm, { ...formProps, noValidate: true, ref: ref, children: [_jsx(FixedHeader, { layoutKind: "tab", children: _jsxs(Wrap, { children: [_jsx("div", { children: leftActions }), _jsx("div", { children: rightActions })] }) }), _jsx(ScrollArea, { layoutKind: "tab", children: _jsxs(Stack, { direction: "vertical", gap: "r24", children: [banner, _jsx(Stack, { direction: "vertical", withSeparators: true, gap: "r24", children: Children.toArray(children) })] }) })] }) })); +}); +const Form = forwardRef(({ layout, requireMode, ...formProps }, ref) => { + return (_jsx(RequireModeContext.Provider, { value: requireMode || 'partial', children: layout.kind === 'page' ? (_jsx(PageForm, { layout: layout, ...formProps, ref: ref })) : (_jsx(TabForm, { layout: layout, ...formProps, ref: ref })) })); +}); +const FieldContext = createContext(null); +const useFieldContext = () => { + const fieldContext = useContext(FieldContext); + if (!fieldContext) { + return { isContextAvailable: false }; + } + return { ...fieldContext, isContextAvailable: true }; +}; +export { Form, FormSection, FormGroup, useFieldContext, DESCRIPTION_PREFIX, LABEL_PREFIX, }; diff --git a/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts b/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts new file mode 100644 index 0000000000..6f54984fbd --- /dev/null +++ b/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts @@ -0,0 +1,19 @@ +export declare const TOP = "top"; +export declare const BOTTOM = "bottom"; +type Position = typeof TOP | typeof BOTTOM; +export type GlobalHealthProps = { + id: string; + alerts: { + description: string; + startsAt: string; + endsAt: string; + severity: string; + }[]; + start: string; + end: string; + height?: number; + tooltipPosition?: Position; +}; +declare function GlobalHealthBar({ id, alerts, start, end, height, tooltipPosition, }: GlobalHealthProps): import("react/jsx-runtime").JSX.Element; +export { GlobalHealthBar }; +//# sourceMappingURL=GlobalHealthBar.component.d.ts.map \ No newline at end of file diff --git a/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map b/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map new file mode 100644 index 0000000000..43f461a09d --- /dev/null +++ b/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"GlobalHealthBar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/globalhealthbar/GlobalHealthBar.component.tsx"],"names":[],"mappings":"AAKA,eAAO,MAAM,GAAG,QAAQ,CAAC;AACzB,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,KAAK,QAAQ,GAAG,OAAO,GAAG,GAAG,OAAO,MAAM,CAAC;AAC3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;IACJ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,QAAQ,CAAC;CAC5B,CAAC;AAEF,iBAAS,eAAe,CAAC,EACvB,EAAE,EACF,MAAM,EACN,KAAK,EACL,GAAG,EACH,MAAU,EACV,eAAqB,GACtB,EAAE,iBAAiB,2CAyKnB;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/globalhealthbar/GlobalHealthBar.component.js b/dist/components/globalhealthbar/GlobalHealthBar.component.js new file mode 100644 index 0000000000..7f33b8e929 --- /dev/null +++ b/dist/components/globalhealthbar/GlobalHealthBar.component.js @@ -0,0 +1,169 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +// @ts-nocheck +import { useMemo } from 'react'; +import { VegaChart } from '../vegachartv2/VegaChartV2.component'; +import { useTheme } from 'styled-components'; +import { formatValue } from './tooltip/index'; +export const TOP = 'top'; +export const BOTTOM = 'bottom'; +function GlobalHealthBar({ id, alerts, start, end, height = 8, tooltipPosition = TOP, }) { + const theme = useTheme(); + const trimAlerts = alerts.map((alert) => { + if (new Date(alert.startsAt) < new Date(start)) { + return { ...alert, startsAt: start }; + } + return { ...alert }; + }); + trimAlerts.unshift({ + startsAt: start, + endsAt: end, + severity: 'healthy', + }); + const spec = { + width: 'container', + height, + data: { + values: trimAlerts, + }, + transform: [ + { + calculate: "datum.description !== '' ? 'View details on alert page' : ''", + as: 'title', + }, + ], + view: { + cornerRadius: 6, + }, + config: { + style: { + cell: { + stroke: 'transparent', + strokeWidth: 0, + }, + }, + }, + layer: [ + // Paint the entire bar with green + { + mark: { + type: 'rect', + clip: true, + }, + encoding: { + color: { + value: theme.statusHealthy, + }, + }, + }, // Paint the timespan as x-axis + { + mark: { + type: 'rect', + cursor: 'pointer', + clip: true, + }, + encoding: { + x: { + field: 'startsAt', + type: 'temporal', + title: null, + stack: null, + axis: { + format: '%d%b %H:%M:%S', + ticks: true, + tickCount: 5, + //A desired number of ticks, for axes visualizing quantitative scales. The resulting number may be different so that values are “nice” (multiples of 2, 5, 10) and lie within the underlying scale’s range. + labelFlush: 20, + labelColor: theme.textSecondary, + }, + }, + x2: { + field: 'endsAt', + }, + color: { + value: theme.statusHealthy, + }, + }, + }, + { + mark: { + type: 'rect', + tooltip: true, + cursor: 'pointer', + clip: true, + }, + params: [ + { + name: 'highlight', + // The supported DOM event types for mark items are https://vega.github.io/vega/docs/event-streams/ + select: { + type: 'point', + on: 'mouseover', + clear: 'mouseout', + }, + }, + ], + encoding: { + x: { + timeUnit: 'yearmonthdatehoursminutes', + field: 'startsAt', + type: 'temporal', + title: null, + }, + x2: { + field: 'endsAt', + }, + color: { + field: 'severity', + type: 'nominal', + title: 'null', + scale: { + domain: ['healthy', 'critical', 'unavailable', 'warning'], + range: [ + theme.statusHealthy, + theme.statusCritical, + theme.textSecondary, + theme.statusWarning, + ], + }, + legend: null, + }, + tooltip: [ + { + field: 'severity', + title: 'Severity', + }, + { + field: 'startsAt', + title: 'Start', + type: 'temporal', + timeUnit: 'yearmonthdatehoursminutes', + }, + { + field: 'endsAt', + title: 'End', + type: 'temporal', + timeUnit: 'yearmonthdatehoursminutes', + }, + { + field: 'title', + title: 'title', + }, + { + field: 'description', + title: 'Description', + }, + ], + opacity: { + condition: { + param: 'highlight', + value: 1, + }, + value: 0.6, + }, + }, + }, + ], + }; + return (_jsx(VegaChart, { className: "sc-globalhealthbar", spec: spec, theme: 'custom', tooltipPosition: tooltipPosition, formatTooltip: useMemo(() => formatValue(), []) })); +} +export { GlobalHealthBar }; diff --git a/dist/components/globalhealthbar/tooltip/index.d.ts b/dist/components/globalhealthbar/tooltip/index.d.ts new file mode 100644 index 0000000000..4605fa6d04 --- /dev/null +++ b/dist/components/globalhealthbar/tooltip/index.d.ts @@ -0,0 +1,8 @@ +/** + * Format the value to be shown in the tooltip. + * + * @param value The value to show in the tooltip. + * @param valueToHtml Function to convert a single cell value to an HTML string + */ +export declare function formatValue(): (value: any, valueToHtml: (value: any) => string, maxDepth: number) => string; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/components/globalhealthbar/tooltip/index.d.ts.map b/dist/components/globalhealthbar/tooltip/index.d.ts.map new file mode 100644 index 0000000000..4e4be79a50 --- /dev/null +++ b/dist/components/globalhealthbar/tooltip/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/globalhealthbar/tooltip/index.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,WAAW,YAEhB,GAAG,eACG,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,YACzB,MAAM,KACf,MAAM,CAwDV"} \ No newline at end of file diff --git a/dist/components/globalhealthbar/tooltip/index.js b/dist/components/globalhealthbar/tooltip/index.js new file mode 100644 index 0000000000..be2b78ffb1 --- /dev/null +++ b/dist/components/globalhealthbar/tooltip/index.js @@ -0,0 +1,55 @@ +// @ts-nocheck +import { stringify } from 'vega-lite'; +import { isArray, isObject, isString } from 'vega-util'; +/** + * Format the value to be shown in the tooltip. + * + * @param value The value to show in the tooltip. + * @param valueToHtml Function to convert a single cell value to an HTML string + */ +export function formatValue() { + return (value, valueToHtml, maxDepth) => { + if (isArray(value)) { + return `[${value + .map((v) => valueToHtml(isString(v) ? v : stringify(v, maxDepth))) + .join(', ')}]`; + } + if (isObject(value)) { + let content = ''; + const { title, image, ...rest } = value; + if (title) { + content += `

${valueToHtml(title)}

`; + } + if (image) { + content += ``; + } + const keys = Object.keys(rest); + if (keys.length > 0) { + content += ''; + for (const key of keys) { + let val = rest[key]; + // ignore undefined properties + if (val === undefined) { + continue; + } + if (isObject(val)) { + val = stringify(val, maxDepth); + } + if (val && val !== 'undefined' && val !== 'null') { + content += ` + + + `; + } + } + content += `
+ ${valueToHtml(key)}: + + ${valueToHtml(val)} +
`; + } + return content || '{}'; // show empty object if there are no properties + } + return valueToHtml(value); + }; +} diff --git a/dist/components/healthselectorv2/HealthSelector.component.d.ts b/dist/components/healthselectorv2/HealthSelector.component.d.ts new file mode 100644 index 0000000000..e5e442c76b --- /dev/null +++ b/dist/components/healthselectorv2/HealthSelector.component.d.ts @@ -0,0 +1,60 @@ +import { OptionProps, SelectProps } from '../selectv2/Selectv2.component'; +type OptionValue = { + label?: string; +} & OptionProps; +type Props = { + options?: OptionValue[]; +} & SelectProps; +export declare const AllStatusIcon: () => import("react/jsx-runtime").JSX.Element; +export declare const defaultOptions: readonly [{ + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "All Status"; + readonly value: "all"; +}, { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Healthy"; + readonly value: "healthy"; +}, { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Warning"; + readonly value: "warning"; +}, { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Critical"; + readonly value: "critical"; +}, { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Unknown"; + readonly value: "unknown"; +}]; +export declare const optionsDefaultConfiguration: { + all: { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "All Status"; + readonly value: "all"; + }; + healthy: { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Healthy"; + readonly value: "healthy"; + }; + warning: { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Warning"; + readonly value: "warning"; + }; + critical: { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Critical"; + readonly value: "critical"; + }; + unknown: { + readonly icon: import("react/jsx-runtime").JSX.Element; + readonly label: "Unknown"; + readonly value: "unknown"; + }; +}; +declare function HealthSelectorv2(props: Props): import("react/jsx-runtime").JSX.Element; +export declare const HealthSelector: typeof HealthSelectorv2; +export {}; +//# sourceMappingURL=HealthSelector.component.d.ts.map \ No newline at end of file diff --git a/dist/components/healthselectorv2/HealthSelector.component.d.ts.map b/dist/components/healthselectorv2/HealthSelector.component.d.ts.map new file mode 100644 index 0000000000..73b9c313d8 --- /dev/null +++ b/dist/components/healthselectorv2/HealthSelector.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"HealthSelector.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/healthselectorv2/HealthSelector.component.tsx"],"names":[],"mappings":"AAIA,OAAO,EACL,WAAW,EAEX,WAAW,EACZ,MAAM,gCAAgC,CAAC;AAExC,KAAK,WAAW,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,WAAW,CAAC;AAChB,KAAK,KAAK,GAAG;IACX,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;CACzB,GAAG,WAAW,CAAC;AAqBhB,eAAO,MAAM,aAAa,+CASzB,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;EA0BjB,CAAC;AAEX,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;CAMvC,CAAC;AAEF,iBAAS,gBAAgB,CAAC,KAAK,EAAE,KAAK,2CAiBrC;AAED,eAAO,MAAM,cAAc,yBAAmB,CAAC"} \ No newline at end of file diff --git a/dist/components/healthselectorv2/HealthSelector.component.js b/dist/components/healthselectorv2/HealthSelector.component.js new file mode 100644 index 0000000000..4008c6ee30 --- /dev/null +++ b/dist/components/healthselectorv2/HealthSelector.component.js @@ -0,0 +1,70 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { useTheme } from 'styled-components'; +import { getThemePropSelector } from '../../utils'; +import { Icon } from '../icon/Icon.component'; +import { Select, } from '../selectv2/Selectv2.component'; +const SelectStyle = styled(Select) ` + .sc-select__control { + background-color: ${getThemePropSelector('buttonSecondary')}; + + &.sc-select__control--is-focused { + background-color: ${getThemePropSelector('buttonSecondary')}; + } + .sc-select__value-container { + overflow: visible; + } + + &.sc-select__control--menu-is-open { + .sc-select__indicator { + transform: rotate(180deg); + } + } + } +`; +export const AllStatusIcon = () => { + const theme = useTheme(); + return (_jsxs("svg", { viewBox: "0 0 150 100", xmlns: "http://www.w3.org/2000/svg", height: "16px", children: [_jsx("circle", { cx: "50", cy: "50", r: "50", fill: theme.statusHealthy }), _jsx("circle", { cx: "75", cy: "50", r: "50", fill: theme.statusWarning }), _jsx("circle", { cx: "100", cy: "50", r: "50", fill: theme.statusCritical })] })); +}; +export const defaultOptions = [ + { + icon: _jsx(AllStatusIcon, {}), + label: 'All Status', + value: 'all', + }, + { + icon: _jsx(Icon, { name: "Check-circle", color: "statusHealthy", size: "lg" }), + label: 'Healthy', + value: 'healthy', + }, + { + icon: _jsx(Icon, { name: "Exclamation-circle", color: "statusWarning", size: "lg" }), + label: 'Warning', + value: 'warning', + }, + { + icon: _jsx(Icon, { name: "Times-circle", color: "statusCritical", size: "lg" }), + label: 'Critical', + value: 'critical', + }, + { + icon: _jsx(Icon, { name: "Info", color: "infoPrimary", size: "lg" }), + label: 'Unknown', + value: 'unknown', + }, +]; +export const optionsDefaultConfiguration = { + all: defaultOptions[0], + healthy: defaultOptions[1], + warning: defaultOptions[2], + critical: defaultOptions[3], + unknown: defaultOptions[4], +}; +function HealthSelectorv2(props) { + const { options = defaultOptions, value, ...selectRest } = props; + let selectValue = value !== null && value !== void 0 ? value : options[0].value; + return (_jsx(SelectStyle, { ...selectRest, value: selectValue, children: options.map((option, index) => { + const { ...optionRest } = option; + return (_jsx(Select.Option, { ...optionRest, children: option.label }, index)); + }) })); +} +export const HealthSelector = HealthSelectorv2; diff --git a/dist/components/icon/Icon.component.d.ts b/dist/components/icon/Icon.component.d.ts new file mode 100644 index 0000000000..b85b36bdea --- /dev/null +++ b/dist/components/icon/Icon.component.d.ts @@ -0,0 +1,157 @@ +import { CSSProperties } from 'react'; +import { CoreUITheme } from '../../style/theme'; +import { SizeProp } from '@fortawesome/fontawesome-svg-core'; +export declare const iconTable: { + Account: string; + Backend: string; + Tape: string; + 'Node-backend': string; + 'Volume-backend': string; + 'Node-pdf': string; + 'Volume-pdf': string; + Network: string; + Bucket: string; + 'Cloud-backend': string; + Datacenter: string; + 'Simple-user': string; + User: string; + Group: string; + Alert: string; + Bell: string; + 'Lat-menu': string; + Dashboard: string; + Workflow: string; + Expiration: string; + Replication: string; + Transition: string; + Discovery: string; + Metrics: string; + Edit: string; + Logs: string; + Lock: string; + 'Lock-open': string; + 'Create-add': string; + Delete: string; + Save: string; + 'External-link': string; + Link: string; + Unlink: string; + Close: string; + 'Dropdown-down': string; + 'Dropdown-up': string; + Search: string; + More: string; + Info: string; + Sync: string; + Export: string; + Copy: string; + 'Simple-upload': string; + Upload: string; + 'Add-plus': string; + Minus: string; + 'Remove-minus': string; + Sort: string; + 'Sort-up': string; + 'Sort-down': string; + Calendar: string; + 'Calendar-minus': string; + 'Arrow-up': string; + 'Arrow-down': string; + 'Arrow-right': string; + 'Arrow-left': string; + 'Arrow-alt-circle-up': string; + Folder: string; + File: string; + 'File-invoice': string; + License: string; + 'Deletion-marker': string; + 'Map-marker': string; + Location: string; + 'Info-circle': string; + 'Exclamation-triangle': string; + 'Exclamation-circle': string; + Exclamation: string; + Check: string; + Protected: string; + 'Chevron-left': string; + 'Chevron-right': string; + 'Chevron-down': string; + 'Chevron-up': string; + 'Angle-right': string; + 'Angle-double-right': string; + Language: string; + Theme: string; + Documentation: string; + Support: string; + EULA: string; + 'Log-out': string; + Hourglass: string; + Pause: string; + 'Pause-circle': string; + 'Play-circle': string; + Upgrade: string; + Expansion: string; + Rebalance: string; + Maintenance: string; + Role: string; + 'Change-erasure': string; + 'Circle-health': string; + 'Circle-empty': string; + 'Dot-circle': string; + 'Check-circle': string; + 'Times-circle': string; + Toolbox: string; + Cubes: string; + Policy: string; + Pen: string; + Pencil: string; + Eye: string; + EyeSlash: string; + Snowflake: string; + Key: string; + Filter: string; + Download: string; + Certificate: string; + Redo: string; + Eraser: string; + 'ID-card': string; + Setting: string; + Desktop: string; + Globe: string; + Satellite: string; + LightMode: string; + DarkMode: string; + News: string; + Ring: string; + Stop: string; + Play: string; +}; +export declare const customIcons: { + 'Remote-user': ({ ariaLabel, color, size }: { + ariaLabel: any; + color: any; + size: any; + }) => import("react/jsx-runtime").JSX.Element; + 'Remote-group': ({ ariaLabel, color, size }: { + ariaLabel: any; + color: any; + size: any; + }) => import("react/jsx-runtime").JSX.Element; +}; +export type IconName = keyof typeof iconTable | keyof typeof customIcons; +export type IconColor = keyof CoreUITheme; +type Props = { + name: IconName; + size?: SizeProp; + color?: IconColor | CSSProperties['color']; + ariaLabel?: string; + withWrapper?: boolean; + style?: CSSProperties; + onClick?: (event: MouseEvent) => void; +}; +export declare const IconWrapper: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, { + size: SizeProp; +}, never>; +declare function Icon({ withWrapper, ...props }: Props): import("react/jsx-runtime").JSX.Element; +export { Icon }; +//# sourceMappingURL=Icon.component.d.ts.map \ No newline at end of file diff --git a/dist/components/icon/Icon.component.d.ts.map b/dist/components/icon/Icon.component.d.ts.map new file mode 100644 index 0000000000..74da1a85c5 --- /dev/null +++ b/dist/components/icon/Icon.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Icon.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/icon/Icon.component.tsx"],"names":[],"mappings":"AAAA,OAAc,EACZ,aAAa,EAKd,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhD,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAG7D,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4HrB,CAAC;AASF,eAAO,MAAM,WAAW;;;;;;;;;;;CAqCvB,CAAC;AAaF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,WAAW,CAAC;AACzE,MAAM,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC;AAC1C,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC,CAAC;AAiBF,eAAO,MAAM,WAAW;UAAsB,QAAQ;SAiCrD,CAAC;AAuEF,iBAAS,IAAI,CAAC,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,2CAU7C;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/icon/Icon.component.js b/dist/components/icon/Icon.component.js new file mode 100644 index 0000000000..e07dccc7bd --- /dev/null +++ b/dist/components/icon/Icon.component.js @@ -0,0 +1,233 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { useEffect, useState, } from 'react'; +import styled, { css, useTheme } from 'styled-components'; +import { Loader } from '../loader/Loader.component'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { useQuery } from 'react-query'; +export const iconTable = { + Account: 'fas faWallet', + Backend: 'fas faNetworkWired', + Tape: 'fas faTape', + 'Node-backend': 'fas faServer', + 'Volume-backend': 'fas faHdd', + 'Node-pdf': 'fas faDatabase', + 'Volume-pdf': 'fas faCompactDisc', + Network: 'fas faProjectDiagram', + Bucket: 'fas faGlassWhiskey', + 'Cloud-backend': 'fas faCloud', + Datacenter: 'fas faWarehouse', + 'Simple-user': 'fas faUser', + User: 'fas faUserCog', + Group: 'fas faUsers', + Alert: 'fas faBell', + Bell: 'far faBell', + 'Lat-menu': 'fas faBars', + Dashboard: 'fas faDesktop', + Workflow: 'fas faRoute', + Expiration: 'fas faStopwatch', + Replication: 'fas faCoins', + Transition: 'fas faRocket', + Discovery: 'fas faReply', + Metrics: 'fas faChartLine', + Edit: 'fas faEdit', + Logs: 'far faFileAlt', + Lock: 'fa faLock', + 'Lock-open': 'fa faLockOpen', + 'Create-add': 'fas faPlus', + Delete: 'fas faTrash', + Save: 'fas faSave', + 'External-link': 'fas faExternalLinkAlt', + Link: 'fas faLink', + Unlink: 'fas faUnlink', + Close: 'fas faTimes', + 'Dropdown-down': 'fas faCaretDown', + 'Dropdown-up': 'fas faCaretUp', + Search: 'fas faSearch', + More: 'fas faEllipsisV', + Info: 'fas faQuestionCircle', + Sync: 'fas faSync', + Export: 'fas faFileExport', + Copy: 'far faClone', + 'Simple-upload': 'fas faUpload', + Upload: 'fas faFileUpload', + 'Add-plus': 'fas faPlusSquare', + Minus: 'fas faMinus', + 'Remove-minus': 'fas faMinusSquare', + Sort: 'fas faSort', + 'Sort-up': 'fas faSortUp', + 'Sort-down': 'fas faSortDown', + Calendar: 'fas faCalendarWeek', + 'Calendar-minus': 'fas faCalendarMinus', + 'Arrow-up': 'fas faArrowUp', + 'Arrow-down': 'fas faArrowDown', + 'Arrow-right': 'fas faArrowRight', + 'Arrow-left': 'fas faArrowLeft', + 'Arrow-alt-circle-up': 'fas faArrowAltCircleUp', + Folder: 'far faFolder', + File: 'far faFile', + 'File-invoice': 'fas faFileInvoice', + License: 'fas faFileInvoice', + 'Deletion-marker': 'fas faBan', + 'Map-marker': 'fas faMapMarkerAlt', + Location: 'fas faMapMarkerAlt', + 'Info-circle': 'fas faInfoCircle', + 'Exclamation-triangle': 'fas faExclamationTriangle', + 'Exclamation-circle': 'fas faExclamationCircle', + Exclamation: 'fas faExclamation', + Check: 'fas faCheck', + Protected: 'fas faShieldAlt', + 'Chevron-left': 'fas faChevronLeft', + 'Chevron-right': 'fas faChevronRight', + 'Chevron-down': 'fas faChevronDown', + 'Chevron-up': 'fas faChevronUp', + 'Angle-right': 'fas faAngleRight', + 'Angle-double-right': 'fas faAngleDoubleRight', + Language: 'fas faLanguage', + Theme: 'fas faPalette', + Documentation: 'fas faClipboardList', + Support: 'fas faComments', + EULA: 'fas faFileContract', + 'Log-out': 'fas faSignOutAlt', + Hourglass: 'far faHourglass', + Pause: 'fas faPause', + 'Pause-circle': 'far faPauseCircle', + 'Play-circle': 'far faPlayCircle', + Upgrade: 'fas faLevelUpAlt', + Expansion: 'fas faExpandAlt', + Rebalance: 'fas faBalanceScale', + Maintenance: 'fas faHardHat', + Role: 'fas faHatCowboy', + 'Change-erasure': 'fas faExchangeAlt', + 'Circle-health': 'fas faCircle', + 'Circle-empty': 'far faCircle', + 'Dot-circle': 'fas faDotCircle', + 'Check-circle': 'fas faCheckCircle', + 'Times-circle': 'fas faTimesCircle', + Toolbox: 'fas faToolbox', + Cubes: 'fas faCubes', + Policy: 'fas faFileSignature', + Pen: 'fa faPen', + Pencil: 'fas faPencilAlt', + Eye: 'fas faEye', + EyeSlash: 'fas faEyeSlash', + Snowflake: 'fas faSnowflake', + Key: 'fas faKey', + Filter: 'fas faFilter', + Download: 'fas faDownload', + Certificate: 'fas faCertificate', + Redo: 'fas faRedoAlt', + Eraser: 'fas faEraser', + 'ID-card': 'fas faIdCard', + Setting: 'fas faCog', //TODO: Rename to Gear in FA v6 + Desktop: 'fas faDesktop', + Globe: 'fas faGlobe', + Satellite: 'fas faSatelliteDish', + LightMode: 'fas faSun', + DarkMode: 'fas faMoon', + News: 'fas faBullhorn', + Ring: 'fas faRing', + Stop: 'fas faStop', + Play: 'fas faPlay', +}; +const getColor = (color) => { + const theme = useTheme(); + if (!color) + return 'currentColor'; + return theme[color] || color; +}; +export const customIcons = { + 'Remote-user': ({ ariaLabel, color, size }) => (_jsxs("svg", { viewBox: "0 0 19 17", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: 'svg-inline--fa ' + (size ? `fa-${size}` : ''), "aria-label": ariaLabel, children: [_jsx("path", { d: "M16.5902 0.5C17.4071 0.5 18.0984 1.1875 18.0984 2V12C18.0984 12.8438 17.4071 13.5 16.5902 13.5H10.5574L11.0601 15H13.3224C13.7309 15 14.0765 15.3438 14.0765 15.75C14.0765 16.1875 13.7309 16.5 13.3224 16.5H4.77596C4.33607 16.5 4.02186 16.1875 4.02186 15.75C4.02186 15.3438 4.33607 15 4.77596 15H7.03825L7.54098 13.5H1.5082C0.659836 13.5 0 12.8438 0 12V2C0 1.1875 0.659836 0.5 1.5082 0.5H16.5902ZM16.0874 11.5V2.5H2.01093V11.5H16.0874Z", fill: getColor(color) }), _jsx("path", { d: "M9.18043 7.97631C8.0165 7.97631 7.08207 7.01268 7.08207 5.81237C7.08207 4.62897 8.0165 3.64844 9.18043 3.64844C10.328 3.64844 11.2788 4.62897 11.2788 5.81237C11.2788 7.01268 10.328 7.97631 9.18043 7.97631ZM10.6394 8.51729C11.8526 8.51729 12.8526 9.54854 12.8526 10.7996V11.4927C12.8526 11.9492 12.4919 12.3042 12.0657 12.3042H6.29519C5.85256 12.3042 5.5083 11.9492 5.5083 11.4927V10.7996C5.5083 9.54854 6.49191 8.51729 7.70502 8.51729H7.98371C8.34437 8.70325 8.7542 8.78778 9.18043 8.78778C9.60666 8.78778 10.0001 8.70325 10.3608 8.51729H10.6394Z", fill: getColor(color) })] })), + 'Remote-group': ({ ariaLabel, color, size }) => (_jsxs("svg", { viewBox: "0 0 19 17", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: 'svg-inline--fa ' + (size ? `fa-${size}` : ''), "aria-label": ariaLabel, children: [_jsx("path", { d: "M16.5902 0.5C17.4071 0.5 18.0984 1.1875 18.0984 2V12C18.0984 12.8438 17.4071 13.5 16.5902 13.5H10.5574L11.0601 15H13.3224C13.7309 15 14.0765 15.3438 14.0765 15.75C14.0765 16.1875 13.7309 16.5 13.3224 16.5H4.77596C4.33607 16.5 4.02186 16.1875 4.02186 15.75C4.02186 15.3438 4.33607 15 4.77596 15H7.03825L7.54098 13.5H1.5082C0.659836 13.5 0 12.8438 0 12V2C0 1.1875 0.659836 0.5 1.5082 0.5H16.5902ZM16.0874 11.5V2.5H2.01093V11.5H16.0874Z", fill: getColor(color) }), _jsx("path", { d: "M4.8 7.85714C4.125 7.85714 3.6 7.29464 3.6 6.57143C3.6 5.8683 4.125 5.28571 4.8 5.28571C5.45625 5.28571 6 5.8683 6 6.57143C6 7.29464 5.45625 7.85714 4.8 7.85714ZM13.2 7.85714C12.525 7.85714 12 7.29464 12 6.57143C12 5.8683 12.525 5.28571 13.2 5.28571C13.8563 5.28571 14.4 5.8683 14.4 6.57143C14.4 7.29464 13.8563 7.85714 13.2 7.85714ZM13.8 8.5C14.4563 8.5 15 9.08259 15 9.78571V10.4286C15 10.7902 14.7188 11.0714 14.4 11.0714H13.1625C13.0313 10.1272 12.5063 9.32366 11.7375 8.8817C11.9625 8.66071 12.2625 8.5 12.6 8.5H13.8ZM9 8.5C7.8375 8.5 6.9 7.49554 6.9 6.25C6.9 5.02455 7.8375 4 9 4C10.1438 4 11.1 5.02455 11.1 6.25C11.1 7.49554 10.1438 8.5 9 8.5ZM10.425 9.14286C11.625 9.14286 12.6 10.1875 12.6 11.4732V12.0357C12.6 12.5781 12.1875 13 11.7 13H6.3C5.79375 13 5.4 12.5781 5.4 12.0357V11.4732C5.4 10.1875 6.35625 9.14286 7.55625 9.14286H7.70625C8.1 9.34375 8.53125 9.46429 9 9.46429C9.45 9.46429 9.88125 9.34375 10.275 9.14286H10.425ZM6.24375 8.8817C5.475 9.32366 4.95 10.1272 4.81875 11.0714H3.6C3.2625 11.0714 3 10.7902 3 10.4286V9.78571C3 9.08259 3.525 8.5 4.2 8.5H5.4C5.71875 8.5 6.01875 8.66071 6.24375 8.8817Z", fill: getColor(color) })] })), +}; +const IconStyled = styled(FontAwesomeIcon) ` + ${(props) => { + const theme = props.theme; + if (props.color && theme[props.color]) { + return css ` + color: ${theme[props.color]}; + `; + } +}} +`; +const DelayedFallback = ({ children, ...rest }) => { + const [show, setShow] = useState(false); + useEffect(() => { + let timeout = setTimeout(() => setShow(true), 300); + return () => { + clearTimeout(timeout); + }; + }, []); + return _jsx("i", { ...rest, children: show && children }); +}; +export const IconWrapper = styled.div ` + ${(props) => { + const brand = props.theme; + return css ` + color: ${brand.infoPrimary}; + border: 1px solid ${brand.infoPrimary}; + background: ${brand.backgroundLevel1}; + ${props.size === 'lg' + ? ` + width: 2.5rem; + height: 2.5rem; + ` + : props.size === 'sm' + ? ` + width: 1.75rem; + height: 1.75rem; + ` + : props.size === 'xs' + ? ` + width: 1.5rem; + height: 1.5rem; + ` + : ` + width: ${parseInt(props.size.replace('x', '')) * 2}rem; + height: ${parseInt(props.size.replace('x', '')) * 2}rem; + `} + `; +}} + + display: flex; + justify-content: center; + align-items: center; + border-radius: 100%; +`; +function NonWrappedIcon({ name, size = '1x', color = undefined, ariaLabel = '', ...rest }) { + const iconInfo = iconTable[name] || customIcons[name]; + if (!iconInfo) + throw new Error(`${name}: is not a valid icon.`); + const { data, status } = useQuery({ + queryKey: ['icon', name], + queryFn: async () => { + if (customIcons[name]) { + return { + default: customIcons[name], + }; + } + const [iconType, iconClass] = iconInfo.split(' '); + try { + const fontAwesomeType = iconType === 'far' + ? 'free-regular-svg-icons' + : 'free-solid-svg-icons'; + const icon = await import(`@fortawesome/${fontAwesomeType}/${iconClass}.js`); + return { + default: ({ name, color, size, ariaLabel, ...rest }) => (_jsx(IconStyled, { color: color, icon: icon[iconClass], size: size, "aria-label": `${name} ${ariaLabel}`, ...rest })), + }; + } + catch { + return { + default: ({ name, ariaLabel }) => (_jsx(Loader, { size: "base", "aria-label": `${name} ${ariaLabel}` })), + }; + } + }, + }); + return (_jsxs(_Fragment, { children: [(status === 'loading' || status === 'error') && (_jsx(DelayedFallback, { "aria-label": `${name} ${ariaLabel}`, children: _jsx(Loader, { size: "base" }) })), status === 'success' && (_jsx(data.default, { name: name, color: color, size: size, ariaLabel: ariaLabel, ...rest }))] })); +} +function Icon({ withWrapper, ...props }) { + if (withWrapper) { + return (_jsx(IconWrapper, { size: props.size || '1x', children: _jsx(NonWrappedIcon, { ...props }) })); + } + return _jsx(NonWrappedIcon, { ...props }); +} +export { Icon }; diff --git a/dist/components/infomessage/InfoMessage.component.d.ts b/dist/components/infomessage/InfoMessage.component.d.ts new file mode 100644 index 0000000000..438fe7bdab --- /dev/null +++ b/dist/components/infomessage/InfoMessage.component.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; +type Props = { + title: string | React.ReactNode; + content: React.ReactNode; + link?: string; +}; +export declare const InfoMessage: ({ title, content, link }: Props) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=InfoMessage.component.d.ts.map \ No newline at end of file diff --git a/dist/components/infomessage/InfoMessage.component.d.ts.map b/dist/components/infomessage/InfoMessage.component.d.ts.map new file mode 100644 index 0000000000..58b97ee3b5 --- /dev/null +++ b/dist/components/infomessage/InfoMessage.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"InfoMessage.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/infomessage/InfoMessage.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAChC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAYF,eAAO,MAAM,WAAW,6BAA8B,KAAK,4CAuB1D,CAAC"} \ No newline at end of file diff --git a/dist/components/infomessage/InfoMessage.component.js b/dist/components/infomessage/InfoMessage.component.js new file mode 100644 index 0000000000..938193d449 --- /dev/null +++ b/dist/components/infomessage/InfoMessage.component.js @@ -0,0 +1,20 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { useTheme } from 'styled-components'; +import { Stack } from '../../spacing'; +import { Icon } from '../icon/Icon.component'; +import { Link, Text } from '../text/Text.component'; +import { useComputeBackgroundColor } from './InfoMessageUtils'; +const InfoMessageContainer = styled.div ` + background-color: ${(props) => props.theme.backgroundLevel2}; + border-radius: 3px; + padding: 0.5rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + color: white; +`; +export const InfoMessage = ({ title, content, link }) => { + const { containerRef, backgroundColor } = useComputeBackgroundColor(); + const theme = useTheme(); + return (_jsxs(InfoMessageContainer, { ref: containerRef, style: { backgroundColor: backgroundColor }, children: [_jsxs(Stack, { children: [_jsx(Icon, { name: "Info-circle", color: theme.infoPrimary, size: "lg" }), typeof title === 'string' ? _jsx(Text, { isEmphazed: true, children: title }) : title] }), _jsx(Text, { color: "textSecondary", isGentleEmphazed: true, children: content }), link && (_jsxs(Link, { href: link, target: "_blank", style: { alignSelf: 'flex-end' }, children: ["More info ", _jsx(Icon, { name: "External-link" })] }))] })); +}; diff --git a/dist/components/infomessage/InfoMessageUtils.d.ts b/dist/components/infomessage/InfoMessageUtils.d.ts new file mode 100644 index 0000000000..f2cb3e080d --- /dev/null +++ b/dist/components/infomessage/InfoMessageUtils.d.ts @@ -0,0 +1,7 @@ +import { DefaultTheme } from 'styled-components'; +export declare const useComputeBackgroundColor: () => { + containerRef: import("react").MutableRefObject; + backgroundColor: string; +}; +export declare const getBackgroundColor: (element: HTMLElement, theme: DefaultTheme) => any; +//# sourceMappingURL=InfoMessageUtils.d.ts.map \ No newline at end of file diff --git a/dist/components/infomessage/InfoMessageUtils.d.ts.map b/dist/components/infomessage/InfoMessageUtils.d.ts.map new file mode 100644 index 0000000000..ac720055ff --- /dev/null +++ b/dist/components/infomessage/InfoMessageUtils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"InfoMessageUtils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/infomessage/InfoMessageUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAY,MAAM,mBAAmB,CAAC;AAI3D,eAAO,MAAM,yBAAyB;;;CAcrC,CAAC;AAEF,eAAO,MAAM,kBAAkB,YACpB,WAAW,SACb,YAAY,QAsBpB,CAAC"} \ No newline at end of file diff --git a/dist/components/infomessage/InfoMessageUtils.js b/dist/components/infomessage/InfoMessageUtils.js new file mode 100644 index 0000000000..5c2bf7b0df --- /dev/null +++ b/dist/components/infomessage/InfoMessageUtils.js @@ -0,0 +1,33 @@ +import { useTheme } from 'styled-components'; +import { hex2RGB } from '../../utils'; +import { useEffect, useRef, useState } from 'react'; +export const useComputeBackgroundColor = () => { + const theme = useTheme(); + const containerRef = useRef(null); + const [backgroundColor, setBackgroundColor] = useState(''); + useEffect(() => { + containerRef.current && + setBackgroundColor(getBackgroundColor(containerRef.current, theme)); + }, [containerRef, theme]); + return { + containerRef, + backgroundColor, + }; +}; +export const getBackgroundColor = (element, theme) => { + if (element.parentElement) { + const parentElementBackgroundColor = window.getComputedStyle(element.parentElement)['background-color']; + if (/rgba\([0-9]+, [0-9]+, [0-9]+, 0\)/.test(parentElementBackgroundColor) || + !window.getComputedStyle(element.parentElement)['background-color']) { + return getBackgroundColor(element.parentElement, theme); + } + else { + const rgbArray = hex2RGB(theme.backgroundLevel2); + if (`rgb(${rgbArray[0]}, ${rgbArray[1]}, ${rgbArray[2]})` === + parentElementBackgroundColor) { + return theme.backgroundLevel3; + } + } + } + return theme.backgroundLevel2; +}; diff --git a/dist/components/inlineinput/InlineInput.d.ts b/dist/components/inlineinput/InlineInput.d.ts new file mode 100644 index 0000000000..fed7fa2700 --- /dev/null +++ b/dist/components/inlineinput/InlineInput.d.ts @@ -0,0 +1,16 @@ +import { InputProps } from '../inputv2/inputv2'; +import { UseMutationResult } from 'react-query'; +type InlineInputForm = { + value: string; +}; +type InlineInputProps = { + defaultValue?: string; + confirmationModal?: { + title: JSX.Element; + body: JSX.Element; + }; + changeMutation: UseMutationResult; +} & InputProps; +export declare const InlineInput: ({ defaultValue, confirmationModal, changeMutation, ...props }: InlineInputProps) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=InlineInput.d.ts.map \ No newline at end of file diff --git a/dist/components/inlineinput/InlineInput.d.ts.map b/dist/components/inlineinput/InlineInput.d.ts.map new file mode 100644 index 0000000000..4668877cc9 --- /dev/null +++ b/dist/components/inlineinput/InlineInput.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"InlineInput.d.ts","sourceRoot":"","sources":["../../../src/lib/components/inlineinput/InlineInput.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAS,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAWhD,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AACF,KAAK,gBAAgB,GAAG;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC;KACnB,CAAC;IACF,cAAc,EAAE,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;CAC/E,GAAG,UAAU,CAAC;AAEf,eAAO,MAAM,WAAW,kEAKrB,gBAAgB,4CA+IlB,CAAC"} \ No newline at end of file diff --git a/dist/components/inlineinput/InlineInput.js b/dist/components/inlineinput/InlineInput.js new file mode 100644 index 0000000000..8f371fe2b2 --- /dev/null +++ b/dist/components/inlineinput/InlineInput.js @@ -0,0 +1,85 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +import { Input } from '../inputv2/inputv2'; +import { Modal } from '../modal/Modal.component'; +import { useToast } from '../toast/ToastProvider'; +import { useForm } from 'react-hook-form'; +import { Text } from '../text/Text.component'; +import { useState } from 'react'; +import { Stack, Wrap } from '../../spacing'; +const UnderlinedText = styled(Text) ` + text-decoration-line: underline; + text-decoration-style: dashed; + cursor: text; +`; +export const InlineInput = ({ defaultValue, confirmationModal, changeMutation, ...props }) => { + const { register, handleSubmit, watch, reset } = useForm({ + defaultValues: { + value: defaultValue, + }, + }); + const [isConfirmationModalOpened, setIsConfirmationModalOpened] = useState(false); + const handleSuccess = () => { + setIsConfirmationModalOpened(false); + setIsEditing(false); + setIsHover(false); + }; + const onSubmit = (data) => { + if (confirmationModal) { + setIsConfirmationModalOpened(true); + } + else { + changeMutation.mutate(data, { + onSuccess: () => { + handleSuccess(); + }, + onError: () => { + showToast({ + open: true, + status: 'error', + message: 'An error occurred while updating the value', + }); + }, + }); + } + }; + const { showToast } = useToast(); + const [isHover, setIsHover] = useState(false); + const [isEditing, setIsEditing] = useState(false); + const handleReset = () => { + reset(); + setIsEditing(false); + setIsHover(false); + }; + //handle esc key to cancel editing + const handleKeyDown = (event) => { + if (event.key === 'Escape') { + handleReset(); + } + }; + if (isEditing) { + return (_jsxs(_Fragment, { children: [_jsx("form", { onSubmit: handleSubmit(onSubmit), children: _jsxs(Stack, { children: [_jsx(Input, { ...register('value'), size: "1/3", autoFocus: true, onKeyDown: handleKeyDown, ...props }), _jsx(Button, { icon: _jsx(Icon, { name: "Close" }), tooltip: { + overlay: 'Cancel', + }, type: "reset", variant: "outline", onClick: handleReset }), _jsx(Button, { icon: _jsx(Icon, { name: "Check" }), tooltip: { + overlay: 'Save', + }, variant: "primary", type: "submit", isLoading: changeMutation.isLoading })] }) }), confirmationModal && (_jsx(Modal, { isOpen: isConfirmationModalOpened, title: confirmationModal.title, footer: _jsxs(Wrap, { children: [_jsx("p", {}), _jsxs(Stack, { children: [_jsx(Button, { label: "Cancel", variant: "outline", onClick: () => setIsConfirmationModalOpened(false) }), _jsx(Button, { label: "Confirm", variant: "primary", isLoading: changeMutation.isLoading, onClick: () => { + changeMutation.mutate(watch(), { + onSuccess: () => { + handleSuccess(); + }, + onError: () => { + showToast({ + open: true, + status: 'error', + message: 'An error occurred while updating the value', + }); + }, + }); + } })] })] }), children: confirmationModal.body }))] })); + } + return (_jsxs(Stack, { onMouseEnter: () => setIsHover(true), onMouseLeave: () => setIsHover(false), onFocus: () => setIsHover(true), onBlur: () => setIsHover(false), children: [_jsx(UnderlinedText, { children: watch('value') }), _jsx(Button, { icon: _jsx(Icon, { name: "Pencil" }), tooltip: { + overlay: 'Edit', + }, variant: "primary", onClick: () => setIsEditing(true), style: { opacity: !isHover ? '0' : '1' } })] })); +}; diff --git a/dist/components/inputlist/InputButtons.d.ts b/dist/components/inputlist/InputButtons.d.ts new file mode 100644 index 0000000000..944a7be533 --- /dev/null +++ b/dist/components/inputlist/InputButtons.d.ts @@ -0,0 +1,19 @@ +import { CSSProperties } from 'styled-components'; +type AddButtonProps = { + index: number; + items: Array; + insertEntry: () => void; + disabled?: boolean; + iconStyle?: CSSProperties; +}; +export declare const AddButton: ({ index, items, insertEntry, disabled, iconStyle, }: AddButtonProps) => import("react/jsx-runtime").JSX.Element; +type SubButtonProps = { + index: number; + items: Array; + deleteEntry: (arg0: number) => void; + disabled?: boolean; + iconStyle?: CSSProperties; +}; +export declare const SubButton: ({ index, items, deleteEntry, disabled, iconStyle, }: SubButtonProps) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=InputButtons.d.ts.map \ No newline at end of file diff --git a/dist/components/inputlist/InputButtons.d.ts.map b/dist/components/inputlist/InputButtons.d.ts.map new file mode 100644 index 0000000000..a4eeb36c94 --- /dev/null +++ b/dist/components/inputlist/InputButtons.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"InputButtons.d.ts","sourceRoot":"","sources":["../../../src/lib/components/inputlist/InputButtons.tsx"],"names":[],"mappings":"AAAA,OAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAgB1D,KAAK,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,SAAS,wDAMnB,cAAc,4CA2ChB,CAAC;AACF,KAAK,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CAAC;AACF,eAAO,MAAM,SAAS,wDAMnB,cAAc,4CAuBhB,CAAC"} \ No newline at end of file diff --git a/dist/components/inputlist/InputButtons.js b/dist/components/inputlist/InputButtons.js new file mode 100644 index 0000000000..05f51ed595 --- /dev/null +++ b/dist/components/inputlist/InputButtons.js @@ -0,0 +1,48 @@ +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { useCallback, useMemo } from 'react'; +import { Box } from '../box/Box'; +import { Icon } from '../icon/Icon.component'; +const CustomButton = styled(Button) ` + ${(props) => !props.isVisible + ? ` + display: none; + ` + : ''} +`; +const isEmptyItem = (item) => item.key === '' && item.value === ''; +export const AddButton = ({ index, items, insertEntry, disabled, iconStyle, }) => { + const itemsLength = items.length; + const itemsIndex = items[index]; + const itemsIndexKey = items[index].key; + const itemsIndexValue = items[index].value; + const isDisabled = useMemo(() => { + if (itemsIndex && itemsIndexKey === '' && itemsIndexValue === '') { + return true; + } + return disabled || false; + }, [itemsIndex, itemsIndexKey, itemsIndexValue, disabled]); + const isVisible = useMemo(() => { + return !(itemsLength > 0 && index !== itemsLength - 1); + }, [itemsLength, index]); + const onClickFn = useCallback(() => { + if (!(itemsLength > 0 && index !== itemsLength - 1)) { + insertEntry(); + } + }, [itemsLength, index, insertEntry]); + return (_jsxs(_Fragment, { children: [!isVisible && _jsx(Box, { ml: 16 }), _jsx(CustomButton, { isVisible: isVisible, type: "button", variant: "outline", disabled: isDisabled, name: `addbtn${index}`, id: `addbtn${index}`, onClick: onClickFn, "aria-label": `Add${index}`, tooltip: { + overlay: 'Add', + placement: 'top', + }, icon: _jsx(Icon, { name: "Add-plus" }) })] })); +}; +export const SubButton = ({ index, items, deleteEntry, disabled, iconStyle, }) => { + let isDisabled = disabled || false; + if (items.length === 1 && isEmptyItem(items[0])) { + isDisabled = true; + } + return (_jsx(Button, { variant: "danger", type: "button", disabled: isDisabled, "aria-label": `Remove${index}`, name: `delbtn${index}`, id: `delbtn${index}`, onClick: () => deleteEntry(index), tooltip: { + overlay: 'Remove', + placement: 'top', + }, icon: _jsx(Icon, { name: "Remove-minus" }) })); +}; diff --git a/dist/components/inputlist/InputList.component.d.ts b/dist/components/inputlist/InputList.component.d.ts new file mode 100644 index 0000000000..d6af6bb01a --- /dev/null +++ b/dist/components/inputlist/InputList.component.d.ts @@ -0,0 +1,16 @@ +import { HTMLProps } from 'react'; +import { RefCallBack } from 'react-hook-form'; +export type InputListProps = Omit, 'size'> & { + ref?: RefCallBack; + min?: string | number; + max?: string | number; + maxLength?: number; + minLength?: number; + pattern?: string; + required?: boolean; + disabled?: boolean; + maxItems?: number; + value: T[]; +}; +export declare const InputList: import("react").ForwardRefExoticComponent, "ref"> & import("react").RefAttributes>; +//# sourceMappingURL=InputList.component.d.ts.map \ No newline at end of file diff --git a/dist/components/inputlist/InputList.component.d.ts.map b/dist/components/inputlist/InputList.component.d.ts.map new file mode 100644 index 0000000000..fb78989cd1 --- /dev/null +++ b/dist/components/inputlist/InputList.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"InputList.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/inputlist/InputList.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAc,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,GAAG;IAC1E,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,CAAC,EAAE,CAAC;CACZ,CAAC;AAgFF,eAAO,MAAM,SAAS,kKAAgC,CAAC"} \ No newline at end of file diff --git a/dist/components/inputlist/InputList.component.js b/dist/components/inputlist/InputList.component.js new file mode 100644 index 0000000000..276336651a --- /dev/null +++ b/dist/components/inputlist/InputList.component.js @@ -0,0 +1,30 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { forwardRef } from 'react'; +import { Box } from '../box/Box'; +import { Input } from '../inputv2/inputv2'; +import { AddButton, SubButton } from './InputButtons'; +function InternalInputList({ onChange, onBlur, min, max, maxLength, minLength, pattern, required, disabled, maxItems, value, name, ...rest }, _) { + const isMaxItemsReached = maxItems !== undefined && maxItems !== null && value.length === maxItems; + const insertEntry = () => { + if (!isMaxItemsReached) { + onChange === null || onChange === void 0 ? void 0 : onChange({ + target: { value: [...(value !== null && value !== void 0 ? value : []), ''] }, + }); + } + }; + const deleteEntry = (entryIndex) => { + const newValues = value.filter((_, index) => index !== entryIndex); + const updatedValues = newValues.length === 0 ? [''] : newValues; + onChange === null || onChange === void 0 ? void 0 : onChange({ + target: { value: updatedValues }, + }); + }; + return (_jsx(_Fragment, { children: value.map((val, index) => (_jsxs(Box, { display: "flex", gap: "0.25rem", alignItems: "center", children: [_jsx(Input, { id: `${name}[${index}]`, "aria-label": `${name}${index}`, size: "1/2", value: val, onChange: (evt) => { + const tempValues = [...value]; + tempValues[index] = evt.target.value; + onChange === null || onChange === void 0 ? void 0 : onChange({ + target: { value: tempValues }, + }); + }, ...rest }), _jsx(SubButton, { index: index, deleteEntry: deleteEntry, items: value, disabled: value.length === 1 && value[0] === '' }, `${name}-delete-${value.join(',') + index}`), _jsx(AddButton, { index: index, insertEntry: insertEntry, items: value, disabled: val === '' || isMaxItemsReached }, `${name}-add-${value.join(',') + index}`)] }, index))) })); +} +export const InputList = forwardRef(InternalInputList); diff --git a/dist/components/inputv2/inputv2.d.ts b/dist/components/inputv2/inputv2.d.ts new file mode 100644 index 0000000000..f3c03bfdec --- /dev/null +++ b/dist/components/inputv2/inputv2.d.ts @@ -0,0 +1,19 @@ +import { InputHTMLAttributes } from 'react'; +import { IconName } from '../icon/Icon.component'; +export declare const convertSizeToRem: (size?: "1" | "2/3" | "1/2" | "1/3") => "14rem" | "6rem" | "10rem" | "20.5rem"; +export type InputSize = '1' | '2/3' | '1/2' | '1/3'; +export type InputProps = { + error?: string; + id: string; + leftIcon?: IconName; + rightIcon?: IconName; + size?: InputSize; +} & Omit, 'size'>; +export declare const Input: import("react").ForwardRefExoticComponent<{ + error?: string; + id: string; + leftIcon?: IconName; + rightIcon?: IconName; + size?: InputSize; +} & Omit, "size"> & import("react").RefAttributes>; +//# sourceMappingURL=inputv2.d.ts.map \ No newline at end of file diff --git a/dist/components/inputv2/inputv2.d.ts.map b/dist/components/inputv2/inputv2.d.ts.map new file mode 100644 index 0000000000..683edee5fa --- /dev/null +++ b/dist/components/inputv2/inputv2.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"inputv2.d.ts","sourceRoot":"","sources":["../../../src/lib/components/inputv2/inputv2.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAIxD,OAAO,EAAQ,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAExD,eAAO,MAAM,gBAAgB,UAAW,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,2CAKlE,CAAC;AAwFF,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,GAAG,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,KAAK;YAPR,MAAM;QACV,MAAM;eACC,QAAQ;gBACP,QAAQ;WACb,SAAS;0GAmDjB,CAAC"} \ No newline at end of file diff --git a/dist/components/inputv2/inputv2.js b/dist/components/inputv2/inputv2.js new file mode 100644 index 0000000000..9749486f9f --- /dev/null +++ b/dist/components/inputv2/inputv2.js @@ -0,0 +1,90 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { forwardRef } from 'react'; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { DESCRIPTION_PREFIX, useFieldContext } from '../form/Form.component'; +import { Icon } from '../icon/Icon.component'; +export const convertSizeToRem = (size) => { + if (size === '2/3') + return '14rem'; + else if (size === '1/3') + return '6rem'; + else if (size === '1/2') + return '10rem'; + else + return '20.5rem'; +}; +const StyledInput = styled.input ` + max-width: ${(props) => props.hasIcon ? `calc(100% - 1rem - ${spacing.f8})` : '100%'}; + + font-family: 'Lato'; + ${(props) => props.disabled && + ` + cursor: not-allowed; + `} + background: ${(props) => props.theme.backgroundLevel1}; + font-size: 1rem; + color: ${(props) => props.theme.textPrimary}; + border: 0; + flex: 1; + border-radius: ${spacing.r4}; + line-height: ${spacing.r20}; + &:placeholder-shown { + font-style: italic; + } + &::placeholder { + color: ${(props) => props.theme.textSecondary}; + opacity: 0.5; + } + &:focus { + border: 0; + outline: none; + } + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus, + &:-webkit-autofill:active { + -webkit-text-fill-color: ${(props) => props.theme.textPrimary}; + -webkit-background-clip: text; + caret-color: ${(props) => props.theme.textPrimary}; + } +`; +const InputContainer = styled.div ` + height: 100%; + display: flex; + align-items: center; + gap: ${spacing.f8}; + padding: 0 ${spacing.r8} 0 ${spacing.r8}; + background: ${(props) => props.theme.backgroundLevel1}; + border-radius: ${spacing.r4}; + ${(props) => props.isContextAvailable && + props.disabled && + ` + opacity: 0.5; + cursor: not-allowed; + `} +`; +const InputBorder = styled.div ` + box-sizing: border-box; + width: ${(props) => props.width}; + height: ${spacing.r32}; + border: ${spacing.r1} solid + ${(props) => props.hasError ? props.theme.statusCritical : props.theme.border}; + border-radius: ${spacing.r4}; + &:hover { + ${(props) => !props.disabled && + `border: ${spacing.r1} solid ${props.theme.infoPrimary};`} + } + &:focus-within { + border: ${spacing.r1} solid ${(props) => props.theme.infoPrimary}; + } +`; +const SelfCenterredIcon = styled(Icon) ` + align-self: center; + color: ${(props) => props.theme.textSecondary}; +`; +export const Input = forwardRef(({ error, disabled, id, leftIcon, rightIcon, placeholder, size, ...inputProps }, ref) => { + const { isContextAvailable, disabled: disabledFromFieldContext, error: errorFromFieldContext, } = useFieldContext(); + placeholder = placeholder ? `Example: ${placeholder}` : undefined; + return (_jsx(InputBorder, { disabled: !!(disabled || disabledFromFieldContext), hasError: !!(error || errorFromFieldContext), width: convertSizeToRem(size), children: _jsxs(InputContainer, { isContextAvailable: isContextAvailable, disabled: !!(disabled || disabledFromFieldContext), hasError: !!(error || errorFromFieldContext), children: [leftIcon && _jsx(SelfCenterredIcon, { name: leftIcon }), _jsx(StyledInput, { ref: ref, disabled: disabled || disabledFromFieldContext, "aria-invalid": !!(error || errorFromFieldContext), "aria-describedby": `${DESCRIPTION_PREFIX}${id}`, hasIcon: !!(leftIcon || rightIcon), id: id, ...inputProps, placeholder: placeholder }), rightIcon && _jsx(SelfCenterredIcon, { name: rightIcon })] }) })); +}); diff --git a/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts b/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts new file mode 100644 index 0000000000..75115ddd40 --- /dev/null +++ b/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts @@ -0,0 +1,8 @@ +import { Props as SidebarProps } from '../sidebar/Sidebar.component'; +type Props = { + sidebar: SidebarProps; + children: JSX.Element; +}; +declare function LateralNavbarLayout({ children, sidebar, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { LateralNavbarLayout }; +//# sourceMappingURL=LateralNavbarLayout.component.d.ts.map \ No newline at end of file diff --git a/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts.map b/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts.map new file mode 100644 index 0000000000..947ca2a76e --- /dev/null +++ b/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LateralNavbarLayout.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/lateralnavbarlayout/LateralNavbarLayout.component.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGrE,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,CAAC;AAiBF,iBAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CASjE;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.js b/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.js new file mode 100644 index 0000000000..04439a1237 --- /dev/null +++ b/dist/components/lateralnavbarlayout/LateralNavbarLayout.component.js @@ -0,0 +1,23 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { Sidebar } from '../sidebar/Sidebar.component'; +import { getThemePropSelector } from '../../utils'; +const LateralNavbarLayoutContainer = styled.div ` + display: flex; + flex-direction: column; + height: 100vh; + width: 100vw; +`; +const ContentContainer = styled.div ` + display: flex; + flex-direction: row; + height: 100vh; +`; +const MainContent = styled.div ` + flex-grow: 1; + background-color: ${getThemePropSelector('backgroundLevel1')}; +`; +function LateralNavbarLayout({ children, sidebar, ...rest }) { + return (_jsx(LateralNavbarLayoutContainer, { className: "sc-lateralnavbarlayout", ...rest, children: _jsxs(ContentContainer, { children: [sidebar && _jsx(Sidebar, { ...sidebar }), _jsx(MainContent, { className: "main", children: children })] }) })); +} +export { LateralNavbarLayout }; diff --git a/dist/components/layout/Layout.component.d.ts b/dist/components/layout/Layout.component.d.ts new file mode 100644 index 0000000000..cf735fb072 --- /dev/null +++ b/dist/components/layout/Layout.component.d.ts @@ -0,0 +1,11 @@ +import { Props as NavbarProps } from '../navbar/Navbar.component'; +import { Props as SidebarProps } from '../sidebar/Sidebar.component'; +type Props = { + navbar?: NavbarProps; + sidebar?: SidebarProps; + navbarElement?: JSX.Element; + children: JSX.Element; +}; +declare function Layout({ children, sidebar, navbar, navbarElement, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Layout }; +//# sourceMappingURL=Layout.component.d.ts.map \ No newline at end of file diff --git a/dist/components/layout/Layout.component.d.ts.map b/dist/components/layout/Layout.component.d.ts.map new file mode 100644 index 0000000000..7d01e6e275 --- /dev/null +++ b/dist/components/layout/Layout.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Layout.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/layout/Layout.component.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGrE,KAAK,KAAK,GAAG;IACX,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAC5B,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,CAAC;AAgBF,iBAAS,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAc3E;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/layout/Layout.component.js b/dist/components/layout/Layout.component.js new file mode 100644 index 0000000000..a408a708ce --- /dev/null +++ b/dist/components/layout/Layout.component.js @@ -0,0 +1,26 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { Navbar } from '../navbar/Navbar.component'; +import { Sidebar } from '../sidebar/Sidebar.component'; +import { getThemePropSelector } from '../../utils'; +const LayoutContainer = styled.div ` + display: flex; + flex-direction: column; + height: 100%; +`; +const ContentContainer = styled.div ` + display: flex; + flex-direction: row; + flex-grow: 1; +`; +const MainContent = styled.div ` + flex-grow: 1; + background-color: ${getThemePropSelector('backgroundLevel1')}; +`; +function Layout({ children, sidebar, navbar, navbarElement, ...rest }) { + return (_jsxs(LayoutContainer, { className: "sc-layout", ...rest, children: [navbar && _jsx(Navbar, { ...navbar }), !navbar && + navbarElement !== undefined && + navbarElement !== null && + navbarElement, _jsxs(ContentContainer, { children: [sidebar && _jsx(Sidebar, { ...sidebar }), _jsx(MainContent, { className: "main", children: children })] })] })); +} +export { Layout }; diff --git a/dist/components/layout/v2/AppContainer.d.ts b/dist/components/layout/v2/AppContainer.d.ts new file mode 100644 index 0000000000..43b81d7830 --- /dev/null +++ b/dist/components/layout/v2/AppContainer.d.ts @@ -0,0 +1,29 @@ +import { ReactElement, ReactNode } from 'react'; +import { ThemeColors } from '../../../style/theme'; +declare function AppContainer({ children, sidebarNavigation, hasPadding, ...rest }: { + children: ReactElement | ReactElement[]; + sidebarNavigation?: ReactElement; + hasPadding?: boolean; +}): import("react/jsx-runtime").JSX.Element; +declare namespace AppContainer { + var ContextContainer: ({ children, background, ...rest }: { + background?: ThemeColors; + children: ReactElement | ReactElement[]; + }) => import("react/jsx-runtime").JSX.Element; + var OverallSummary: ({ children, noPadding, noBottomMargin, hasTopMargin, background, ...rest }: { + children: any; + noPadding?: boolean; + noBottomMargin?: boolean; + hasTopMargin?: boolean; + background?: ThemeColors; + }) => import("react/jsx-runtime").JSX.Element; + var MainContent: ({ children, hasPadding, background, hasTopMargin, ...rest }: { + children: ReactNode; + hasPadding?: boolean; + hasTopMargin?: boolean; + background?: ThemeColors; + }) => import("react/jsx-runtime").JSX.Element; + var sectionDistance: string; +} +export { AppContainer }; +//# sourceMappingURL=AppContainer.d.ts.map \ No newline at end of file diff --git a/dist/components/layout/v2/AppContainer.d.ts.map b/dist/components/layout/v2/AppContainer.d.ts.map new file mode 100644 index 0000000000..85299f6b12 --- /dev/null +++ b/dist/components/layout/v2/AppContainer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AppContainer.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/v2/AppContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAmInD,iBAAS,YAAY,CAAC,EACpB,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACV,GAAG,IAAI,EACR,EAAE;IACD,QAAQ,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IACxC,iBAAiB,CAAC,EAAE,YAAY,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,2CASA;kBAlBQ,YAAY;8DA/FlB;QACD,UAAU,CAAC,EAAE,WAAW,CAAC;QACzB,QAAQ,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;KACzC;qGA8BE;QACD,QAAQ,EAAE,GAAG,CAAC;QACd,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,UAAU,CAAC,EAAE,WAAW,CAAC;KAC1B;mFA8BE;QACD,QAAQ,EAAE,SAAS,CAAC;QACpB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,UAAU,CAAC,EAAE,WAAW,CAAC;KAC1B;;;AA8CD,OAAO,EAAE,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/layout/v2/AppContainer.js b/dist/components/layout/v2/AppContainer.js new file mode 100644 index 0000000000..878fc17469 --- /dev/null +++ b/dist/components/layout/v2/AppContainer.js @@ -0,0 +1,63 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { spacing } from '../../../spacing'; +const Container = styled.div ` + display: flex; + flex-direction: row; + flex: 1; + overflow: hidden; +`; +const FillAvailableFlexBox = styled.div ` + flex: 1; + width: 100%; + box-sizing: border-box; + overflow: hidden; +`; +const sectionDistance = spacing.r2; +const ContextWrapper = styled.div ` + background: ${(props) => props.background ? props.theme[props.background] : 'initial'}; + height: 2.5rem; + min-height: 2.5rem; + max-height: 2.5rem; + box-sizing: border-box; + display: flex; + align-items: center; + width: 100%; +`; +const ContextContainer = ({ children, background, ...rest }) => (_jsx(ContextWrapper, { background: background, children: _jsx(FillAvailableFlexBox, { ...rest, children: children }) })); +const OverallSummaryContainer = styled.div ` + background: ${(props) => props.theme[props.background || 'backgroundLevel2']}; + min-height: 6rem; + padding: ${({ noPadding }) => (noPadding ? '0' : '0 1rem')}; + margin-bottom: ${({ noBottomMargin }) => noBottomMargin ? '0' : sectionDistance}; + margin-top: ${({ hasTopMargin }) => (hasTopMargin ? '1rem' : '0')}; + box-sizing: border-box; + display: flex; + align-items: center; +`; +const OverallSummary = ({ children, noPadding, noBottomMargin, hasTopMargin, background, ...rest }) => (_jsx(OverallSummaryContainer, { background: background, noPadding: noPadding, noBottomMargin: noBottomMargin, hasTopMargin: hasTopMargin, children: _jsx(FillAvailableFlexBox, { ...rest, children: children }) })); +const MainContentContainer = styled.div ` + display: flex; + flex: 1; + padding: ${(props) => (props.hasPadding ? '1rem' : 'initial')}; + margin-top: ${({ hasTopMargin }) => (hasTopMargin ? '1rem' : '0')}; + background: ${(props) => props.theme[props.background || 'backgroundLevel3']}; + overflow: hidden; +`; +const MainContent = ({ children, hasPadding, background, hasTopMargin, ...rest }) => (_jsx(MainContentContainer, { hasPadding: hasPadding, hasTopMargin: hasTopMargin, background: background, ...rest, children: children })); +const AppChildrenContainer = styled.div ` + flex: 1; + display: flex; + flex-direction: column; + padding: ${(props) => (props.hasPadding ? '0 1rem' : 'initial')}; + width: 100%; + box-sizing: border-box; +`; +function AppContainer({ children, sidebarNavigation, hasPadding, ...rest }) { + return (_jsxs(Container, { ...rest, children: [sidebarNavigation, _jsx(AppChildrenContainer, { hasPadding: hasPadding, children: children })] })); +} +AppContainer.ContextContainer = ContextContainer; +AppContainer.OverallSummary = OverallSummary; +AppContainer.MainContent = MainContent; +AppContainer.sectionDistance = sectionDistance; +export { AppContainer }; diff --git a/dist/components/layout/v2/index.d.ts b/dist/components/layout/v2/index.d.ts new file mode 100644 index 0000000000..4e083ee319 --- /dev/null +++ b/dist/components/layout/v2/index.d.ts @@ -0,0 +1,6 @@ +import { ReactElement } from 'react'; +export declare function Layout({ children: app, headerNavigation, }: { + children: ReactElement | ReactElement[]; + headerNavigation: ReactElement; +}): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/components/layout/v2/index.d.ts.map b/dist/components/layout/v2/index.d.ts.map new file mode 100644 index 0000000000..eb6d220894 --- /dev/null +++ b/dist/components/layout/v2/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/v2/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAgBrC,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EAAE,GAAG,EACb,gBAAgB,GACjB,EAAE;IACD,QAAQ,EAAE,YAAY,GAAG,YAAY,EAAE,CAAC;IACxC,gBAAgB,EAAE,YAAY,CAAC;CAChC,2CAOA"} \ No newline at end of file diff --git a/dist/components/layout/v2/index.js b/dist/components/layout/v2/index.js new file mode 100644 index 0000000000..861ffa48fa --- /dev/null +++ b/dist/components/layout/v2/index.js @@ -0,0 +1,16 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { navbarHeight } from '../../../style/theme'; +const LayoutContainer = styled.div ` + display: flex; + flex-direction: column; + height: 100vh; + box-sizing: border-box; + background: ${(props) => props.theme['backgroundLevel1']}; +`; +const Navigation = styled.div ` + height: ${navbarHeight}; +`; +export function Layout({ children: app, headerNavigation, }) { + return (_jsxs(LayoutContainer, { className: "layout-container", children: [_jsx(Navigation, { children: headerNavigation }), app] })); +} diff --git a/dist/components/layout/v2/panels.d.ts b/dist/components/layout/v2/panels.d.ts new file mode 100644 index 0000000000..226a37ade7 --- /dev/null +++ b/dist/components/layout/v2/panels.d.ts @@ -0,0 +1,17 @@ +import { ReactElement } from 'react'; +import { ThemeColors } from '../../../style/theme'; +type RatioString = '50-50' | '65-35' | '30-70'; +export declare const TwoPanelLayout: ({ panelsRatio, leftPanel, rightPanel, noGap, ...rest }: { + panelsRatio: RatioString; + leftPanel: { + children: ReactElement; + background?: ThemeColors; + }; + rightPanel: { + children: ReactElement; + background?: ThemeColors; + }; + noGap?: boolean; +}) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=panels.d.ts.map \ No newline at end of file diff --git a/dist/components/layout/v2/panels.d.ts.map b/dist/components/layout/v2/panels.d.ts.map new file mode 100644 index 0000000000..1e3986f726 --- /dev/null +++ b/dist/components/layout/v2/panels.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/v2/panels.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAwDnD,KAAK,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAgB/C,eAAO,MAAM,cAAc,2DAMxB;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,UAAU,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IAChE,UAAU,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAC;QAAC,UAAU,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IACjE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,4CAmBA,CAAC"} \ No newline at end of file diff --git a/dist/components/layout/v2/panels.js b/dist/components/layout/v2/panels.js new file mode 100644 index 0000000000..67c559fc5a --- /dev/null +++ b/dist/components/layout/v2/panels.js @@ -0,0 +1,52 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { AppContainer } from './AppContainer'; +const ThirtySeventy = { + left: 0.3, + right: 0.7, +}; +const SixtyFiveThirtyFive = { + left: 0.65, + right: 0.35, +}; +// const SeventyThirty: Ratio = { +// left: 0.7, +// right: 0.3, +// }; +const FiftyFifty = { + left: 0.5, + right: 0.5, +}; +const PanelsContainer = styled.div ` + display: flex; + flex: 1; + gap: ${({ noGap }) => (noGap ? 0 : AppContainer.sectionDistance)}; +`; +const LeftPanel = styled.div ` + flex: ${(props) => props.flex || '0 auto'}; + background: ${(props) => props.theme[props.background || 'backgroundLevel3']}; + display: flex; + min-width: 0; +`; +const RightPanel = styled.div ` + flex: ${(props) => props.flex || '0 auto'}; + background: ${(props) => props.theme[props.background || 'backgroundLevel4']}; + display: flex; + min-width: 0; +`; +function getPanelsObjectRation(ratio) { + if (ratio === '50-50') { + return FiftyFifty; + } + if (ratio === '65-35') { + return SixtyFiveThirtyFive; + } + if (ratio === '30-70') { + return ThirtySeventy; + } + throw new Error('Unsupported ratio'); +} +export const TwoPanelLayout = ({ panelsRatio, leftPanel, rightPanel, noGap, ...rest }) => { + const panelsObjectRatio = getPanelsObjectRation(panelsRatio); + return (_jsxs(PanelsContainer, { noGap: noGap, ...rest, children: [_jsx(LeftPanel, { flex: panelsObjectRatio.left, background: leftPanel.background, children: leftPanel.children }), _jsx(RightPanel, { flex: panelsObjectRatio.right, background: rightPanel.background, children: rightPanel.children })] })); +}; diff --git a/dist/components/linechart/LineChart.component.d.ts b/dist/components/linechart/LineChart.component.d.ts new file mode 100644 index 0000000000..4b6e979afa --- /dev/null +++ b/dist/components/linechart/LineChart.component.d.ts @@ -0,0 +1,21 @@ +import { $PropertyType } from 'utility-types'; +import type { Encoding, Field } from 'vega-lite'; +type Props = { + id: string; + data: Array>; + xAxis: Record; + yAxis: Array>; + color?: Record; + tooltip?: boolean; + lineConfig?: Record; + width?: number; + height?: number; + displayTrendLine?: boolean; + strokeDashEncodingConfig?: $PropertyType, 'strokeDash'>; + opacityEncodingConfig?: $PropertyType, 'opacity'>; + tooltipConfig?: $PropertyType, 'tooltip'>; + tooltipTheme?: 'light' | 'dark' | 'custom'; +}; +declare function LineChart({ id, data, xAxis, yAxis, color, tooltip, lineConfig, height, width, displayTrendLine, strokeDashEncodingConfig, opacityEncodingConfig, tooltipConfig, tooltipTheme, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { LineChart }; +//# sourceMappingURL=LineChart.component.d.ts.map \ No newline at end of file diff --git a/dist/components/linechart/LineChart.component.d.ts.map b/dist/components/linechart/LineChart.component.d.ts.map new file mode 100644 index 0000000000..84ed40f137 --- /dev/null +++ b/dist/components/linechart/LineChart.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LineChart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linechart/LineChart.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACjD,KAAK,KAAK,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,wBAAwB,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,CAAC;IACxE,qBAAqB,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;IAClE,aAAa,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;IAC1D,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;CAC5C,CAAC;AAEF,iBAAS,SAAS,CAAC,EACjB,EAAE,EACF,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAe,EACf,UAAU,EACV,MAAY,EACZ,KAAY,EACZ,gBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,GAAG,IAAI,EACR,EAAE,KAAK,2CAgHP;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/linechart/LineChart.component.js b/dist/components/linechart/LineChart.component.js new file mode 100644 index 0000000000..bbc300f727 --- /dev/null +++ b/dist/components/linechart/LineChart.component.js @@ -0,0 +1,109 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { VegaChart } from '../vegachart/VegaChart.component'; +function LineChart({ id, data, xAxis, yAxis, color, tooltip = false, lineConfig, height = 300, width = 1000, displayTrendLine = false, strokeDashEncodingConfig, opacityEncodingConfig, tooltipConfig, tooltipTheme, ...rest }) { + // hardcode the trendline configuration for tooltip + const trendline = { + mark: 'rule', + selection: { + index: { + type: 'single', + on: 'mousemove', + encodings: ['x'], + nearest: true, + }, + }, + encoding: { + color: { + condition: { + selection: { + not: 'index', + }, + value: 'transparent', + }, + }, + }, + }; + /* + ** strokeDash encoding allows to define a field in data items that defines the line stroke dash property + ** this would allow to get same color lines but having some dashed and some plains + ** https://vega.github.io/vega-lite/docs/line.html#multi-series-line-chart-with-varying-dashes + */ + /* + ** opacity Encoding allows to define rules for each line's opacity + */ + const lines = yAxis.map((y) => ({ + mark: { + type: 'line', + ...lineConfig, + }, + encoding: { + y, + strokeDash: strokeDashEncodingConfig, + opacity: opacityEncodingConfig, + }, + })); + const currentTimeTrendline = { + mark: { + type: 'rule', + style: 'ruleCurrentTime', + color: 'white', + opacity: 0.2, + }, + encoding: { + x: { + value: width / 2, + }, + y: { + value: height, + }, + y2: { + value: 0, + }, + }, + }; + const topTrendline = { + mark: { + type: 'rule', + style: 'ruleTop', + color: 'orange', + opacity: 0.2, + }, + encoding: { + y: { + aggregate: 'max', + field: 'capacity', + type: 'quantitative', + }, + x: { + value: 0, + }, + x2: { + value: width, + }, + }, + }; + const spec = { + data: { + values: data, + }, + encoding: { + x: xAxis, + color, + // To disable tooltips for a particular single view specification, you can set the "tooltip" property of a mark definition block to null. + tooltip: tooltip ? [xAxis, ...yAxis] : null, + }, + height, + width, + layer: [...lines], + ...rest, + }; + if (tooltip) { + spec.layer.push(tooltipConfig || trendline); + } + if (displayTrendLine) { + spec.layer.push(currentTimeTrendline); + spec.layer.push(topTrendline); + } + return (_jsx(VegaChart, { id: id, spec: spec, theme: tooltipTheme || 'light' })); +} +export { LineChart }; diff --git a/dist/components/linetemporalchart/ChartUtil.d.ts b/dist/components/linetemporalchart/ChartUtil.d.ts new file mode 100644 index 0000000000..bfc32a79c5 --- /dev/null +++ b/dist/components/linetemporalchart/ChartUtil.d.ts @@ -0,0 +1,40 @@ +import { Serie } from './LineTemporalChart.component'; +import './LineTemporalChart.component'; +export type VegaData = { + timestamp: number; + label: string; + value: number | 'NAN'; + isNegativeValue: boolean; + isDashed: boolean; +}[]; +export declare function normlizeVegaFieldName(fieldName: string): string; +export declare function convert2VegaData(addedMissingDataPointSeries: Serie[]): VegaData; +export declare function convertDataBaseValue(data: VegaData, base: number): VegaData; +/** + * Return the unit label base on the current dataset, and the valueBase which is used to convert the data + * @param {any} unitRange + * @param {any} maxValue the maximum value among the data set + * @returns {any} + */ +export declare function getUnitLabel(unitRange: { + threshold: number; + label: string; +}[], maxValue: number): { + valueBase: number; + unitLabel: string; +}; +/** + * This function manually adds the missing data points with `null` value caused by downtime of the VMs + * + * @param {array} orginalValues - The array of the data points are already sorted according to the time series + * @param {number} startingTimeStamp - The starting timestamp in seconds + * @param {number} sampleDuration - The time span value in seconds + * @param {number} sampleFrequency - The time difference between two data points in seconds + * + */ +export declare function addMissingDataPoint(orginalValues: [number, string | null][], startingTimeStamp: number, sampleDuration: number, sampleFrequency: number): [number, string | null][]; +export declare const getRelativeValue: (value: number, base: number) => number; +export declare const relativeDatumToOriginalDatum: (datum: T, base: number) => T; +export declare const getAbsoluteValue: (relativeValue: number, base: number) => number; +export declare const getColorDomains: (series: Serie[]) => string[]; +//# sourceMappingURL=ChartUtil.d.ts.map \ No newline at end of file diff --git a/dist/components/linetemporalchart/ChartUtil.d.ts.map b/dist/components/linetemporalchart/ChartUtil.d.ts.map new file mode 100644 index 0000000000..ef366efa5d --- /dev/null +++ b/dist/components/linetemporalchart/ChartUtil.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ChartUtil.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetemporalchart/ChartUtil.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,+BAA+B,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;IAEtB,eAAe,EAAE,OAAO,CAAC;IAEzB,QAAQ,EAAE,OAAO,CAAC;CACnB,EAAE,CAAC;AAKJ,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,UAEtD;AACD,wBAAgB,gBAAgB,CAC9B,2BAA2B,EAAE,KAAK,EAAE,GACnC,QAAQ,CAqBV;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,EACH,QAAQ,EAAE,MAAM,GACf;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAkCA;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,EACxC,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAsC3B;AAGD,eAAO,MAAM,gBAAgB,UAAW,MAAM,QAAQ,MAAM,WAE3D,CAAC;AACF,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS,CAAC,QAAQ,MAAM,KAAG,CAQxE,CAAC;AACF,eAAO,MAAM,gBAAgB,kBAAmB,MAAM,QAAQ,MAAM,WAEnE,CAAC;AAEF,eAAO,MAAM,eAAe,WAAY,KAAK,EAAE,KAAG,MAAM,EAMvD,CAAC"} \ No newline at end of file diff --git a/dist/components/linetemporalchart/ChartUtil.js b/dist/components/linetemporalchart/ChartUtil.js new file mode 100644 index 0000000000..4397ac2056 --- /dev/null +++ b/dist/components/linetemporalchart/ChartUtil.js @@ -0,0 +1,126 @@ +import './LineTemporalChart.component'; +import { NAN_STRING } from '../constants'; +//Given a field containing dots ".", vega is interpreting this as an accessor +//for nested objects, breaking then the internal mechnism to retrieve tooltip +//data from the mouse position. We are fixing it by replacing the dots by a +//well-known string that we expect no one would use to label a serie. +export function normlizeVegaFieldName(fieldName) { + return fieldName.replace(/(\.)/g, 'VEGADOESNTSUPPORTDOTINFIELDNAME'); +} +export function convert2VegaData(addedMissingDataPointSeries) { + const flatArr = []; + addedMissingDataPointSeries.forEach((line) => { + line.data.forEach((datum) => { + const obj = { + timestamp: datum[0] * 1000, + // convert to million second + label: normlizeVegaFieldName(line.getTooltipLabel(line.metricPrefix, line.resource)), + resource: line.resource, + value: datum[1] && datum[1] !== NAN_STRING ? Number(datum[1]) : NAN_STRING, + isNegativeValue: line.metricPrefix === 'read' || line.metricPrefix === 'out', + isDashed: line.isLineDashed || false, + }; + flatArr.push(obj); + }); + }); + return flatArr; +} +// base on the current base value, convert the original vegadata to +export function convertDataBaseValue(data, base) { + return data.map((datum) => { + return { + ...datum, + value: typeof datum.value === 'number' + ? getRelativeValue(datum.value, base) + : NAN_STRING, + }; + }); +} +/** + * Return the unit label base on the current dataset, and the valueBase which is used to convert the data + * @param {any} unitRange + * @param {any} maxValue the maximum value among the data set + * @returns {any} + */ +export function getUnitLabel(unitRange, maxValue) { + // first sort the unitRange + unitRange.sort((unitA, unitB) => { + return unitA.threshold - unitB.threshold; + }); + let index = unitRange.findIndex((range) => range.threshold > maxValue); + // last unit + if (index === -1) { + index = unitRange.length; + } + if (index === 0) { + return { + valueBase: unitRange[index].threshold, + unitLabel: unitRange[index].label, + }; + } + return { + valueBase: unitRange[index - 1].threshold, + unitLabel: unitRange[index - 1].label, + }; +} +/** + * This function manually adds the missing data points with `null` value caused by downtime of the VMs + * + * @param {array} orginalValues - The array of the data points are already sorted according to the time series + * @param {number} startingTimeStamp - The starting timestamp in seconds + * @param {number} sampleDuration - The time span value in seconds + * @param {number} sampleFrequency - The time difference between two data points in seconds + * + */ +export function addMissingDataPoint(orginalValues, startingTimeStamp, sampleDuration, sampleFrequency) { + if (!orginalValues || + startingTimeStamp === undefined || + !sampleDuration || + !sampleFrequency || + startingTimeStamp < 0 || + sampleDuration <= 0 || + sampleFrequency <= 0) { + return []; + } + const newValues = []; + const numberOfDataPoints = sampleDuration / sampleFrequency + 1; + let samplingPointTime = startingTimeStamp; + // initialize the array with all "NAN" value, in order for the tooltip to display dash(-) + for (let i = 0; i < numberOfDataPoints; i++) { + newValues.push([samplingPointTime, NAN_STRING]); + samplingPointTime += sampleFrequency; + } + // copy the existing data points from `orginalValue` array to `newValues` + if (newValues.length === 0) + return []; + let nextIndex = 0; + for (let i = 0; i < newValues.length; i++) { + if (orginalValues[nextIndex] && + newValues[i][0] === orginalValues[nextIndex][0]) { + newValues[i][1] = orginalValues[nextIndex][1]; + nextIndex++; + } + } + return newValues; +} +// get the value for the based value +// TODO: We need to handle the negative value in the future +export const getRelativeValue = (value, base) => { + return value / (base || 1); +}; +export const relativeDatumToOriginalDatum = (datum, base) => { + // $FlowFixMe + return Object.fromEntries(Object.entries(datum).map(([key, value]) => [ + key, + getAbsoluteValue(value, base), + ])); +}; +export const getAbsoluteValue = (relativeValue, base) => { + return relativeValue * (base || 1); +}; +// extract the labels from getTooltipLabel function to define the domain in color +export const getColorDomains = (series) => { + return series.map((serie) => { + return normlizeVegaFieldName(serie.getTooltipLabel(serie.metricPrefix, serie.resource)); + }); +}; diff --git a/dist/components/linetemporalchart/LineTemporalChart.component.d.ts b/dist/components/linetemporalchart/LineTemporalChart.component.d.ts new file mode 100644 index 0000000000..be9a65d917 --- /dev/null +++ b/dist/components/linetemporalchart/LineTemporalChart.component.d.ts @@ -0,0 +1,42 @@ +export declare const YAXIS_TITLE_READ_WRITE = "write(+) / read(-)"; +export declare const YAXIS_TITLE_IN_OUT = "in(+) / out(-)"; +export declare const UNIT_RANGE_BS: { + threshold: number; + label: string; +}[]; +export type Serie = { + resource: string; + data: [number, string | null][]; + getTooltipLabel: (metricPrefix?: string, resource?: string) => string; + getLegendLabel?: (metricPrefix?: string, resource?: string) => string; + color?: string; + metricPrefix?: string; + isLineDashed?: boolean; +}; +export type LineChartProps = { + series: Serie[]; + title: string; + height: number; + startingTimeStamp: number; + unitRange?: { + threshold: number; + label: string; + }[]; + isLoading?: boolean; + isLegendHidden?: boolean; + yAxisType?: 'default' | 'percentage' | 'symmetrical'; + yAxisTitle?: string; + helpText?: string | JSX.Element; + onHover?: (dataPoint: any) => void; + renderTooltipSerie?: (arg0: { + color?: string; + isLineDashed?: boolean; + name: string; + value: string; + key: string; + unitLabel: string; + }, tooltipData: any) => string; +}; +declare function LineTemporalChart({ series, title, height, startingTimeStamp, unitRange, isLoading, isLegendHidden, yAxisType, yAxisTitle, helpText, renderTooltipSerie, onHover, ...rest }: LineChartProps): import("react/jsx-runtime").JSX.Element; +export { LineTemporalChart }; +//# sourceMappingURL=LineTemporalChart.component.d.ts.map \ No newline at end of file diff --git a/dist/components/linetemporalchart/LineTemporalChart.component.d.ts.map b/dist/components/linetemporalchart/LineTemporalChart.component.d.ts.map new file mode 100644 index 0000000000..d12e42e4df --- /dev/null +++ b/dist/components/linetemporalchart/LineTemporalChart.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LineTemporalChart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetemporalchart/LineTemporalChart.component.tsx"],"names":[],"mappings":"AAoCA,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAC3D,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,aAAa;;;GAqBzB,CAAC;AA+BF,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IAEjB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAEhC,eAAe,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAEtE,cAAc,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAEtE,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAE1B,SAAS,CAAC,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IACJ,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,aAAa,CAAC;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,kBAAkB,CAAC,EAAE,CACnB,IAAI,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KACnB,EACD,WAAW,EAAE,GAAG,KACb,MAAM,CAAC;CACb,CAAC;AAkCF,iBAAS,iBAAiB,CAAC,EACzB,MAAM,EACN,KAAK,EACL,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,SAAiB,EACjB,cAAsB,EACtB,SAAqB,EACrB,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,OAAO,EACP,GAAG,IAAI,EACR,EAAE,cAAc,2CAomBhB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/linetemporalchart/LineTemporalChart.component.js b/dist/components/linetemporalchart/LineTemporalChart.component.js new file mode 100644 index 0000000000..67739c2465 --- /dev/null +++ b/dist/components/linetemporalchart/LineTemporalChart.component.js @@ -0,0 +1,575 @@ +import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime"; +// @ts-nocheck +import { useMemo, useRef, useLayoutEffect, Fragment } from 'react'; +import styled, { useTheme } from 'styled-components'; +import { lighten, darken } from 'polished'; +import { expressionFunction } from 'vega'; +import { lineColor1, lineColor2, lineColor3, lineColor4, lineColor5, lineColor6, lineColor7, lineColor8, } from '../../style/theme'; +import { VegaChart } from '../vegachartv2/VegaChartV2.component'; +import { useCursorX } from '../vegachartv2/SyncedCursorCharts'; +import { ChartTitleText } from '../text/Text.component'; +import { convert2VegaData, getUnitLabel, convertDataBaseValue, addMissingDataPoint, getRelativeValue, getColorDomains, relativeDatumToOriginalDatum, normlizeVegaFieldName, } from './ChartUtil'; +import { useMetricsTimeSpan } from './MetricTimespanProvider'; +import { spacing } from '../../spacing'; +import { SmallerText } from '../text/Text.component'; +import { Loader } from '../loader/Loader.component'; +import { formatValue } from './tooltip/index'; +import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component'; +import { Icon } from '../icon/Icon.component'; +// some predefined values +export const YAXIS_TITLE_READ_WRITE = 'write(+) / read(-)'; +export const YAXIS_TITLE_IN_OUT = 'in(+) / out(-)'; +export const UNIT_RANGE_BS = [ + { + threshold: 0, + label: 'B/s', + }, + { + threshold: 1024, + label: 'KiB/s', + }, + { + threshold: 1024 * 1024, + label: 'MiB/s', + }, + { + threshold: 1024 * 1024 * 1024, + label: 'GiB/s', + }, + { + threshold: 1024 * 1024 * 1024 * 1024, + label: 'TiB/s', + }, +]; +const LineTemporalChartWrapper = styled.div ` + display: flex; + flex-direction: column; + justify-content: flex-start; // to make sure the header, the graph itself and legend are aligned +`; +const Legends = styled.div ` + display: flex; + align-items: center; +`; +const LegendStroke = styled.div ` + margin: 0 ${spacing.r8} 0 ${spacing.r16}; + height: ${spacing.r2}; + background: ${(props) => props.isLineDashed + ? `repeating-linear-gradient(to right,${props.lineColor} 0,${props.lineColor} ${spacing.r1},transparent ${spacing.r1},transparent ${spacing.r2})` + : props.lineColor}; + width: ${spacing.r8}; +`; +const ChartHeader = styled.div ` + display: flex; + align-items: center; +`; +// Custom formatter to display negative value as an absolute value in read/write, in/out chart +expressionFunction('negativeValueFormatter', function (datum) { + return Math.abs(datum).toFixed(2); +}); +// We use 8 main color from the palette and decline them (lighter/ darker) when we have more than 8 datasets +const colorRange = [ + lineColor1, + lineColor2, + lineColor3, + lineColor4, + lineColor5, + lineColor6, + lineColor7, + lineColor8, + lighten(0.3, lineColor1), + lighten(0.3, lineColor2), + lighten(0.3, lineColor3), + lighten(0.3, lineColor4), + lighten(0.3, lineColor5), + lighten(0.3, lineColor6), + lighten(0.3, lineColor7), + lighten(0.3, lineColor8), + darken(0.2, lineColor1), + darken(0.2, lineColor2), + darken(0.2, lineColor3), + darken(0.2, lineColor4), + darken(0.3, lineColor5), + darken(0.3, lineColor6), + darken(0.3, lineColor7), + darken(0.3, lineColor8), +]; +// Note: we need to make sure the start time and end timefor the prometheus query between the series are the same. +function LineTemporalChart({ series, title, height, startingTimeStamp, unitRange, isLoading = false, isLegendHidden = false, yAxisType = 'default', yAxisTitle, helpText, renderTooltipSerie, onHover, ...rest }) { + // property validation + if (!['default', 'percentage', 'symmetrical'].includes(yAxisType)) { + console.error(`Invalid yAxisType props, expected default, percentage or symmetrical but received ${yAxisType}`); + } + if (!height) { + console.error('Please specify the height of the chart.'); + } + if (!title) { + console.error('Please specify the title of the chart.'); + } + // we have to make sure that when prop unitRange exists, there is at least one item defined. + if (unitRange) { + if (unitRange.length === 0) { + console.error('Please provide at least one entry in unitRange.'); + } + } + const vegaViewRef = useRef(); + const theme = useTheme(); + const { frequency, duration } = useMetricsTimeSpan(); + //##### Data Transformation Start + /** + * 1. Add missing data points + * During the downtime of the platform, there is no data returned by Prometheus API. + * Hence, we can see a line link the last data point before the downtime and the first data point once the platform restarts. + * However, this is not what we expect to see. + * So we need to manually add the missing data points with the value `null` to make sure there is nothing displayed on the graph during the downtime. + */ + const addedMissingDataPointSeries = useMemo(() => { + return series.map((line) => { + return { + ...line, + data: addMissingDataPoint(line.data, startingTimeStamp, duration, frequency), + }; + }); + }, [series, startingTimeStamp, duration, frequency]); + // 2. Change the data structure to a flat array which is required by Vega-lite + const vegaData = useMemo(() => { + return convert2VegaData(addedMissingDataPointSeries); + }, [addedMissingDataPointSeries]); + // 3. Search for the biggest value in order to define the unit for the chart, if the unit is needed. + const maxValue = useMemo(() => { + return Math.max.apply(Math, vegaData.map(function (datum) { + if (datum.value && typeof datum.value === 'number') { + return datum.value; + } + return 0; + })); + }, [vegaData]); + // 4. Recompute the value base on the unit + const valueBase = useMemo(() => { + return unitRange ? getUnitLabel(unitRange, maxValue).valueBase : 1; + }, [maxValue, unitRange]); + const vegaDataWithUnit = unitRange + ? convertDataBaseValue(vegaData, valueBase) + : vegaData; + // 5. Convert the values of metric prefix `read` and `out` to negative. + const vegaSpecValues = vegaDataWithUnit.map((data) => { + if (data.isNegativeValue && + data.value && + typeof data.value === 'number') { + return { ...data, value: 0 - data.value }; + } + else + return { ...data }; + }); + //##### Data Transformation End + const customizedColorRange = useMemo(() => { + const customizedColors = []; + series.map((line) => { + if (line.color) { + return customizedColors.push(line.color); + } + }); + return customizedColors; + }, [series]); + // $FlowFixMe + const seriesResources = [...new Set(series.map((serie) => serie.resource))]; + // for the series with the same resource, the color of legend and tooltip should be the same. + const legendLabels = useMemo(() => { + const uniqueLabel = []; + series.forEach((serie, index) => { + if (serie.getLegendLabel) { + const legend = serie.getLegendLabel(serie.metricPrefix, serie.resource); + if (!uniqueLabel.find((uLabel) => uLabel === legend)) { + const serieIndex = yAxisType === 'symmetrical' && !customizedColorRange.length + ? seriesResources.findIndex((serieResource) => serieResource === serie.resource) + : index; + uniqueLabel.push({ + legend, + serie, + serieIndex, + }); + } + } + }); + return uniqueLabel; + }, [series]); + const tooltipLabels = useMemo(() => series.map((line) => { + return line.getTooltipLabel(line.metricPrefix, line.resource); + }), [series]); + const syncedVerticalRuler = { + mark: 'rule', + encoding: { + x: { + datum: { + expr: 'toDate(cursorX)', + }, // convert the timestamp in milliseconds to Date object + //https://vega.github.io/vega-lite/docs/datetime.html + }, + color: { + value: theme.selectedActive, + }, + /* + According to the design, the vertical ruler should be hided when the mouse points out of the graph area. + We can use param `isCursorDisplayed` to control the size of the vertical line. + */ + size: { + value: 0, + condition: { + test: 'isCursorDisplayed', + value: 1, + }, + }, + }, + }; + const syncedVerticalRulerPercentage = { + mark: 'rule', + encoding: { + x: { + datum: { + expr: 'toDate(cursorX)', + }, // convert the timestamp to Date object + }, + // We draw the line manually for the percentage chart to solve the issue that the synced vertical line can + // only reach the max value one the line. + y: { + datum: 0, + }, + y2: { + datum: 100, + }, + color: { + value: theme.highlight, + opacity: 0.3, + }, + /* + According to the design, the vertical ruler should be hided when the mouse points out of the graph area. + We can use param `isCursorDisplayed` to control the size of the vertical line. + */ + size: { + value: 0, + condition: { + test: 'isCursorDisplayed', + value: 1, + }, + }, + }, + }; + const syncedVerticalRulerSymmetrical = { + mark: 'rule', + encoding: { + x: { + datum: { + expr: 'toDate(cursorX)', + }, // convert the timestamp to Date object + }, + y: { + expr: '-yAxisMaxValue', + }, + y2: { + expr: 'yAxisMaxValue', + }, + color: { + value: theme.highlight, + opacity: 0.3, + }, + /* + According to the design, the vertical ruler should be hided when the mouse points out of the graph area. + We can use param `isCursorDisplayed` to control the size of the vertical line. + */ + size: { + value: 0, + condition: { + test: 'isCursorDisplayed', + value: 1, + }, + }, + }, + }; + const xAxis = { + field: 'timestamp', + type: 'temporal', + axis: { + // Refer to all the available time format: https://github.com/d3/d3-time-format#locale_format + format: '%d %b %H:%M', + ticks: true, + tickCount: 5, + labelColor: theme.textSecondary, + // TODO: labelFontSize is not responsiveness + labelSeparation: 12, // The minimum separation that must be between label bounding boxes for them to be considered non-overlapping (default 0). This property is ignored if labelOverlap resolution is not enabled. + }, + title: null, + }; + const yAxis = useMemo(() => { + return { + field: 'value', + type: 'quantitative', + axis: { + title: yAxisTitle ? yAxisTitle : ' ', + orient: 'right', + translate: -5, + // translate both the x and y coordinates by 5 pixel + tickOffset: 5, + // shift back the y translate to make sure the tick align with the 0 seperation line + labelBaseline: 'middle', + labelPadding: 6, + labelFlush: true, + }, + scale: yAxisType === 'symmetrical' + ? { + domain: [ + { + expr: '-yAxisMaxValue', + }, + { + expr: 'yAxisMaxValue', + }, + ], + } + : yAxisType === 'percentage' + ? { + domain: [0, 100], + } + : undefined, + }; + }, [yAxisTitle, yAxisType]); + const symmetricalColorRange = yAxisType !== 'symmetrical' + ? colorRange + : series.map((serie) => colorRange[seriesResources.indexOf(serie.resource)]); + const color = { + field: 'label', + type: 'nominal', + scale: { + domain: getColorDomains(series), + // the order of the domain should be the same as the order of colorRange, otherwise the colors will be assigned to the line base on the alphabetical order: ; + range: customizedColorRange.length + ? customizedColorRange + : symmetricalColorRange, //if there is no customized color range, we will use the default the line color + }, + legend: null, + }; + // In order to add the tooltip we refered this example + // https://vega.github.io/vega-lite/examples/interactive_multi_line_pivot_tooltip.html + const getTooltipConfig = (fields) => { + const tooltipConfigBase = { + // The pivot transform maps unique values from a field to new aggregated fields (columns) in the output stream. + // https://vega.github.io/vega-lite/docs/pivot.html + transform: [ + { + pivot: 'label', + value: 'value', + groupby: ['timestamp'], + }, + ], + mark: 'rule', + encoding: { + x: xAxis, + opacity: { + // to be check if we can remove this channel, since we don't need to have a rule next to the tooltip + condition: { + value: 0, + selection: 'hover', + }, + value: 0, + }, + tooltip: [ + { + field: 'timestamp', + type: 'temporal', + axis: { + format: '%d %b %H:%M:%S', + ticks: true, + tickCount: 4, + labelAngle: -50, + labelColor: '#B5B5B5', + }, + title: 'title', + }, + ], + }, + selection: { + hover: { + type: 'single', + fields: ['timestamp'], + nearest: true, + on: 'mouseover', + empty: 'none', + clear: 'mouseout', + }, + }, + }; + if (fields.length) { + const newFields = [...tooltipConfigBase.encoding.tooltip, ...fields]; + const newConfig = Object.assign({}, tooltipConfigBase); + newConfig.encoding.tooltip = newFields; + return newConfig; + } + return tooltipConfigBase; + }; + const tooltipConfig = useMemo(() => getTooltipConfig((() => { + const res = []; + tooltipLabels.forEach((label) => { + res.push({ + field: `${normlizeVegaFieldName(label)}`, + type: 'quantitative', + title: `${label}`, + format: '.2f', + formatType: 'negativeValueFormatter', + }); + }); + return res; + })()), [tooltipLabels]); + // we need to retrieve the vega view in order to update the signal + useLayoutEffect(() => { + if (vegaViewRef.current && yAxisType === 'symmetrical') { + vegaViewRef.current + .signal('yAxisMaxValue', Math.ceil(getRelativeValue(maxValue, valueBase))) + .run(); + } + }, [maxValue, valueBase, vegaViewRef, yAxisType]); + // $FlowFixMe + const cursorX = useCursorX().cursorX; + // the specification of the Vega-lite chart + const spec = { + data: { + values: vegaSpecValues, + }, + height, + width: 'container', + // set responsive width + mark: { + type: 'line', + tooltip: true, + }, + // Add two params to control the display of the vertical ruler. + params: [ + { + name: 'cursorX', + value: cursorX || Date.now(), // the value of signal can't be null + }, + { + name: 'isCursorDisplayed', + value: false, + }, + ], + layer: [ + { + encoding: { + x: xAxis, + y: yAxis, + strokeDash: { + field: 'isDashed', + type: 'nominal', + legend: null, + condition: { + test: 'datum.isDashed === true', + value: [4, 2], // Change the value here if the dash is not visible. https://vega.github.io/vega-lite/docs/mark.html#stroke + }, + }, + color: color, + opacity: { + condition: { + test: 'datum.isDashed === true', + // for the dashed line, set the opacity to 0.5 + value: 0.6, + }, + value: 1, + }, + }, + layer: [ + { + mark: { + type: 'line', + strokeWidth: 1, + }, + }, // the width of the line should be 1px + { + mark: 'point', + encoding: { + size: { + value: 0, + condition: { + selection: 'hover', + value: 10, + }, + }, + }, + }, + yAxisType === 'percentage' + ? { + // for percentage chart we need to manually draw the line from 0-100 + ...syncedVerticalRuler, + encoding: { + ...syncedVerticalRuler.encoding, + ...syncedVerticalRulerPercentage.encoding, + }, + } + : yAxisType === 'symmetrical' + ? { + // for symmetrical chart we manually draw the line from minValue to maxValue + ...syncedVerticalRuler, + encoding: { + ...syncedVerticalRuler.encoding, + ...syncedVerticalRulerSymmetrical.encoding, + }, + } + : syncedVerticalRuler, + ], + }, + tooltipConfig, + ], + ...rest, + }; + // the seperation line for symmetrical charts + const seperationLine = { + mark: 'rule', + encoding: { + y: { + datum: 0, + }, + color: { + value: theme.border, + opacity: 1, + }, + }, + }; + if (yAxisType === 'symmetrical') { + spec.layer.unshift(seperationLine); + spec.params.push({ + name: 'yAxisMaxValue', + value: Math.ceil(getRelativeValue(maxValue, valueBase)), + }); + } + const seriesNames = series + .map((serie) => title + serie.resource + (serie.metricPrefix ? serie.metricPrefix : '')) + .join(','); + const unitLabel = unitRange + ? getUnitLabel(unitRange, maxValue).unitLabel + : yAxisType === 'percentage' + ? '%' + : ''; + return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(ChartHeader, { children: [unitLabel ? (_jsxs(ChartTitleText, { children: [title, " (", unitLabel, ")"] }) // for the chart doesn't have title + ) : (_jsx(ChartTitleText, { children: title })), helpText && (_jsx(TooltipComponent, { placement: "bottom-right", overlay: _jsx(SmallerText, { style: { + minWidth: '15rem', + display: 'block', + }, children: helpText }), children: _jsx(Icon, { name: "Info", color: theme.buttonSecondary }) })), isLoading && (_jsx(Loader, { style: { + paddingLeft: `${spacing.r4}`, + } }))] }), _jsx(VegaChart, { spec: spec, onHover: (datum) => { + if (onHover) { + onHover({ + ...datum, + metadata: { + unitLabel, + valueBase, + }, + originalData: { + ...relativeDatumToOriginalDatum(datum, valueBase), + timestamp: datum.timestamp, + }, + }); + } + }, theme: 'custom', ref: vegaViewRef, formatTooltip: useMemo(() => formatValue(series, customizedColorRange, colorRange, unitLabel, yAxisType, renderTooltipSerie), [unitLabel, seriesNames, renderTooltipSerie]) }, seriesNames), !isLegendHidden && (_jsx(Legends, { children: legendLabels.map(({ legend, serie, serieIndex }, index) => { + return (_jsxs(Fragment, { children: [_jsx(LegendStroke, { lineColor: customizedColorRange.length + ? customizedColorRange[serieIndex] + : colorRange[serieIndex], isLineDashed: serie.isLineDashed }), _jsx(SmallerText, { children: legend })] }, `${title}-${legend}-${index}`)); + }) }))] })); +} +export { LineTemporalChart }; diff --git a/dist/components/linetemporalchart/MetricTimespanProvider.d.ts b/dist/components/linetemporalchart/MetricTimespanProvider.d.ts new file mode 100644 index 0000000000..239fade2bc --- /dev/null +++ b/dist/components/linetemporalchart/MetricTimespanProvider.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +import { QueryTimeSpan } from '../constants'; +export declare const MetricsTimeSpanContext: React.Context; +export declare const MetricsTimeSpanProvider: ({ children, }: { + children: JSX.Element; +}) => import("react/jsx-runtime").JSX.Element; +export declare const useMetricsTimeSpan: () => QueryTimeSpan; +//# sourceMappingURL=MetricTimespanProvider.d.ts.map \ No newline at end of file diff --git a/dist/components/linetemporalchart/MetricTimespanProvider.d.ts.map b/dist/components/linetemporalchart/MetricTimespanProvider.d.ts.map new file mode 100644 index 0000000000..bd515995e5 --- /dev/null +++ b/dist/components/linetemporalchart/MetricTimespanProvider.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MetricTimespanProvider.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetemporalchart/MetricTimespanProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,eAAO,MAAM,sBAAsB,qCAA4C,CAAC;AAChF,eAAO,MAAM,uBAAuB,kBAEjC;IACD,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,4CA4BA,CAAC;AACF,eAAO,MAAM,kBAAkB,QAAO,aAUrC,CAAC"} \ No newline at end of file diff --git a/dist/components/linetemporalchart/MetricTimespanProvider.js b/dist/components/linetemporalchart/MetricTimespanProvider.js new file mode 100644 index 0000000000..b7d955cac2 --- /dev/null +++ b/dist/components/linetemporalchart/MetricTimespanProvider.js @@ -0,0 +1,31 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { useEffect, useState, createContext, useContext } from 'react'; +import { useLocation } from 'react-router-dom'; +import { queryTimeSpansCodes } from '../constants'; +export const MetricsTimeSpanContext = createContext(null); +export const MetricsTimeSpanProvider = ({ children, }) => { + // the default timespan is the last 24h + const [queryTimeSpanCode, setQueryTimeSpanCode] = useState(queryTimeSpansCodes[1]); + const urlSearchParams = new URLSearchParams(useLocation().search); + const queryTimeSpan = urlSearchParams.get('from'); + // Sync url timespan to local timespan + useEffect(() => { + if (queryTimeSpan) { + const queryTimeSpanCode = queryTimeSpansCodes.find((item) => item.query === queryTimeSpan); + if (queryTimeSpanCode && queryTimeSpanCode.label) { + setQueryTimeSpanCode(queryTimeSpanCode); + } + else { + console.error('Unexpected timespan query parameter defined in the URL.'); + } + } + }, [queryTimeSpan]); + return (_jsx(MetricsTimeSpanContext.Provider, { value: queryTimeSpanCode, children: children })); +}; +export const useMetricsTimeSpan = () => { + const metricsTimeSpanContext = useContext(MetricsTimeSpanContext); + if (!metricsTimeSpanContext) { + throw new Error("useMetricsTimeSpan hook can't be use outside "); + } + return metricsTimeSpanContext; +}; diff --git a/dist/components/linetemporalchart/tooltip/index.d.ts b/dist/components/linetemporalchart/tooltip/index.d.ts new file mode 100644 index 0000000000..0c7a5672e9 --- /dev/null +++ b/dist/components/linetemporalchart/tooltip/index.d.ts @@ -0,0 +1,30 @@ +import { Options } from 'vega-tooltip'; +import { Handler } from 'vega-tooltip'; +import { Serie } from '../LineTemporalChart.component'; +export declare function defaultRenderTooltipSerie({ color, isLineDashed, name, value, key, }: { + color?: string; + isLineDashed?: boolean; + name: string; + value: string; + key: string; +}): string; +export declare class TooltipHandlerWithPaint extends Handler { + constructor(options?: Options, onHover?: (datum: any) => void); + newCall(handler: any, event: MouseEvent, item: any, value: any): void; + paint(): void; +} +/** + * Format the value to be shown in the tooltip. + * + * @param value The value to show in the tooltip. + * @param valueToHtml Function to convert a single cell value to an HTML string + */ +export declare function formatValue(series: Serie[], customizedColorRange: string[], colorRange: string[], unitLabel: string, yAxisType?: 'default' | 'percentage' | 'symmetrical', renderTooltipSerie?: (arg0: { + color?: string; + isLineDashed?: boolean; + name: string; + value: string; + key: string; + unitLabel: string; +}, tooltipData: any) => string): (value: any, valueToHtml: (value: any) => string, maxDepth: number) => string; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/components/linetemporalchart/tooltip/index.d.ts.map b/dist/components/linetemporalchart/tooltip/index.d.ts.map new file mode 100644 index 0000000000..4e4ae7861f --- /dev/null +++ b/dist/components/linetemporalchart/tooltip/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/linetemporalchart/tooltip/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,wBAAgB,yBAAyB,CAAC,EACxC,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,KAAK,EACL,GAAG,GACJ,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,UAsBA;AACD,qBAAa,uBAAwB,SAAQ,OAAO;gBACtC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI;IAO7D,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG;IAgB9D,KAAK;CAGN;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,KAAK,EAAE,EACf,oBAAoB,EAAE,MAAM,EAAE,EAC9B,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,aAAa,EACpD,kBAAkB,GAAE,CAClB,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB,EACD,WAAW,EAAE,GAAG,KACb,MAAkC,WAG9B,GAAG,eACG,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,YACzB,MAAM,KACf,MAAM,CA8EV"} \ No newline at end of file diff --git a/dist/components/linetemporalchart/tooltip/index.js b/dist/components/linetemporalchart/tooltip/index.js new file mode 100644 index 0000000000..79dcf37914 --- /dev/null +++ b/dist/components/linetemporalchart/tooltip/index.js @@ -0,0 +1,104 @@ +// @ts-nocheck +import { stringify } from 'vega-lite'; +import { Handler } from 'vega-tooltip'; +import { isArray, isObject, isString } from 'vega-util'; +import { spacing } from '../../../style/theme'; +export function defaultRenderTooltipSerie({ color, isLineDashed, name, value, key, }) { + return ` + + ${color !== undefined + ? `` + : ''} + + + ${name} + + + ${value} + + `; +} +export class TooltipHandlerWithPaint extends Handler { + constructor(options, onHover) { + super(options); + this.prevCall = this.call; + this.onHover = onHover; + this.call = this.newCall.bind(this); + } + newCall(handler, event, item, value) { + if (item && + this.onHover && + JSON.stringify(value) !== JSON.stringify(this.value)) { + this.onHover(item.datum.datum); + } + this.handler = handler; + this.event = event; + this.item = item; + this.value = value; + this.prevCall(handler, event, item, value); + } + paint() { + this.prevCall(this.handler, this.event, this.item, this.value); + } +} +/** + * Format the value to be shown in the tooltip. + * + * @param value The value to show in the tooltip. + * @param valueToHtml Function to convert a single cell value to an HTML string + */ +export function formatValue(series, customizedColorRange, colorRange, unitLabel, yAxisType, renderTooltipSerie = defaultRenderTooltipSerie) { + return (value, valueToHtml, maxDepth) => { + if (isArray(value)) { + return `[${value + .map((v) => valueToHtml(isString(v) ? v : stringify(v, maxDepth))) + .join(', ')}]`; + } + if (isObject(value)) { + let content = ''; + const { title, image, ...rest } = value; + if (title) { + content += `

${valueToHtml(title)}

`; + } + if (image) { + content += ``; + } + const keys = Object.keys(rest); + if (keys.length > 0) { + content += ''; + for (const key of keys) { + let val = rest[key]; + // ignore undefined properties + if (val === undefined) { + continue; + } + if (isObject(val)) { + val = stringify(val, maxDepth); + } + const currentSerie = series.find((serie) => serie.getTooltipLabel(serie.metricPrefix, serie.resource) === key); + const currentSerieIndex = series.findIndex((serie) => serie.getTooltipLabel(serie.metricPrefix, serie.resource) === key); + const serieIndex = yAxisType === 'symmetrical' && !customizedColorRange.length // $FlowFixMe + ? [...new Set(series.map((serie) => serie.resource))].findIndex((serieResource) => serieResource === + (currentSerie ? currentSerie.resource : null)) + : currentSerieIndex; + const serieColorRange = customizedColorRange.length + ? customizedColorRange + : colorRange; + content += renderTooltipSerie({ + key, + color: serieIndex !== -1 ? serieColorRange[serieIndex] : undefined, + isLineDashed: serieIndex !== -1 ? series[serieIndex].isLineDashed : undefined, + name: valueToHtml(key), + value: val !== 'NaN' ? `${valueToHtml(val)} ${unitLabel}` : '-', + unitLabel, + }, value); + } + content += `
`; + } + return content || '{}'; // show empty object if there are no properties + } + return valueToHtml(value); + }; +} diff --git a/dist/components/loader/Loader.component.d.ts b/dist/components/loader/Loader.component.d.ts new file mode 100644 index 0000000000..26f161b4b5 --- /dev/null +++ b/dist/components/loader/Loader.component.d.ts @@ -0,0 +1,10 @@ +import { LOADER_SIZE as SIZE } from '../constants'; +type Props = { + size?: keyof typeof SIZE; + color?: string; + children?: JSX.Element; + centered?: boolean; +}; +declare function Loader({ children, color, size, centered, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Loader }; +//# sourceMappingURL=Loader.component.d.ts.map \ No newline at end of file diff --git a/dist/components/loader/Loader.component.d.ts.map b/dist/components/loader/Loader.component.d.ts.map new file mode 100644 index 0000000000..e61e4f8db1 --- /dev/null +++ b/dist/components/loader/Loader.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Loader.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/loader/Loader.component.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,cAAc,CAAC;AACnD,KAAK,KAAK,GAAG;IACX,IAAI,CAAC,EAAE,MAAM,OAAO,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAoCF,iBAAS,MAAM,CAAC,EACd,QAAQ,EACR,KAAiB,EACjB,IAAiB,EACjB,QAAgB,EAChB,GAAG,IAAI,EACR,EAAE,KAAK,2CAeP;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/loader/Loader.component.js b/dist/components/loader/Loader.component.js new file mode 100644 index 0000000000..d76663685b --- /dev/null +++ b/dist/components/loader/Loader.component.js @@ -0,0 +1,41 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { LoaderIcon } from '../../icons/scality-loading'; +import { fontSize, svgSize } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { LOADER_SIZE as SIZE } from '../constants'; +const LoaderContainer = styled.div ` + display: flex; + ${(props) => { + return css ` + font-size: ${fontSize[props.size]}; + svg { + height: ${svgSize[props.size]}; + width: ${svgSize[props.size]}; + fill: ${props.color}; + } + `; +}} + + ${(props) => { + if (props.centered) + return css ` + height: 100vh; + justify-content: center; + align-items: center; + `; +}} +`; +const LoaderText = styled.span ` + padding: 10px 0; + color: ${getThemePropSelector('textPrimary')}; +`; +const LoaderTextDiv = styled.span ` + display: flex; + flex-flow: column; + align-items: center; +`; +function Loader({ children, color = '#A14FBF', size = SIZE.large, centered = false, ...rest }) { + return (_jsx(LoaderContainer, { size: size, color: color, centered: centered, className: "sc-loader", ...rest, children: _jsxs(LoaderTextDiv, { children: [_jsx(LoaderIcon, {}), children && _jsxs(LoaderText, { children: [" ", children] })] }) })); +} +export { Loader }; diff --git a/dist/components/modal/Modal.component.d.ts b/dist/components/modal/Modal.component.d.ts new file mode 100644 index 0000000000..cd076d9116 --- /dev/null +++ b/dist/components/modal/Modal.component.d.ts @@ -0,0 +1,13 @@ +import { ReactNode } from 'react'; +type Props = { + isOpen: boolean; + close?: () => void; + title: ReactNode; + footer?: ReactNode; + children: ReactNode; + subTitle?: ReactNode; + role?: 'dialog' | 'alertdialog'; +}; +declare const Modal: ({ isOpen, close, title, children, footer, subTitle, role, ...rest }: Props) => import("react").ReactPortal | null; +export { Modal }; +//# sourceMappingURL=Modal.component.d.ts.map \ No newline at end of file diff --git a/dist/components/modal/Modal.component.d.ts.map b/dist/components/modal/Modal.component.d.ts.map new file mode 100644 index 0000000000..316319634d --- /dev/null +++ b/dist/components/modal/Modal.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Modal.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/modal/Modal.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAsC,MAAM,OAAO,CAAC;AAUtE,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;CACjC,CAAC;AA0CF,QAAA,MAAM,KAAK,wEASR,KAAK,uCAmEP,CAAC;AAEF,OAAO,EAAE,KAAK,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/modal/Modal.component.js b/dist/components/modal/Modal.component.js new file mode 100644 index 0000000000..3d0ec4c331 --- /dev/null +++ b/dist/components/modal/Modal.component.js @@ -0,0 +1,81 @@ +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; +import { useEffect, useLayoutEffect, useRef } from 'react'; +import ReactDom from 'react-dom'; +import styled from 'styled-components'; +import { Wrap, spacing } from '../../spacing'; +import { zIndex } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +import { Text } from '../text/Text.component'; +const ModalContainer = styled.div ` + position: fixed; + top: 0; + left: 0; + display: flex; + height: 100%; + width: 100%; + justify-content: center; + align-items: center; + background-color: rgba(0, 0, 0, 0.5); + z-index: ${zIndex.modal}; +`; +const ModalContent = styled.div ` + display: flex; + flex-direction: column; + background-color: ${getThemePropSelector('backgroundLevel1')}; + color: ${getThemePropSelector('textPrimary')}; + border-radius: 5px; + overflow: hidden; + min-width: 250px; + min-height: 150px; + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + max-height: calc(100vh - ${spacing.r24} - ${spacing.r24}); +`; +const ModalHeader = styled.div ` + display: flex; + padding: ${spacing.r16} ${spacing.r16} ${spacing.r16} ${spacing.r32}; + background-color: ${(props) => props.theme.backgroundLevel3}; +`; +const ModalBody = styled.div ` + padding: ${spacing.r32}; + flex-grow: 1; + background-color: ${(props) => props.theme.backgroundLevel4}; + overflow-y: auto; +`; +const ModalFooter = styled.div ` + padding: ${spacing.r16}; + background-color: ${(props) => props.theme.backgroundLevel3}; +`; +const Modal = ({ isOpen, close, title, children, footer, subTitle, role = 'dialog', ...rest }) => { + const modalContainer = useRef(document.createElement('div')); + useLayoutEffect(() => { + document.body && document.body.prepend(modalContainer.current); + return () => { + document.body && document.body.removeChild(modalContainer.current); + }; + }, [modalContainer]); + useEffect(() => { + if (isOpen) { + //Auto focus the modal when it opens + modalContainer.current.setAttribute('tabindex', '0'); + modalContainer.current.focus(); + //Listen to esc key to close the modal + const handleEsc = (event) => { + if (event.key === 'Escape') { + close && close(); + } + }; + document.addEventListener('keydown', handleEsc); + return () => { + document.removeEventListener('keydown', handleEsc); + }; + } + }, [isOpen]); + return isOpen + ? ReactDom.createPortal(_jsx(ModalContainer, { className: "sc-modal", role: role, "aria-modal": "true", "aria-labelledby": "dialog_label", "aria-describedby": "dialog_desc", ...rest, children: _jsxs(ModalContent, { className: "sc-modal-content", children: [_jsx(ModalHeader, { className: "sc-modal-header", children: _jsxs(Wrap, { style: { flex: 1 }, children: [_jsx(Text, { variant: "Larger", id: "dialog_label", children: title }), close ? (_jsx(Button, { icon: _jsx(Icon, { name: "Close" }), onClick: close, tooltip: { + overlay: 'Close modal', + } })) : (_jsx(_Fragment, { children: subTitle }))] }) }), _jsx(ModalBody, { className: "sc-modal-body", id: "dialog_desc", children: children }), footer && (_jsx(ModalFooter, { className: "sc-modal-footer", children: footer }))] }) }), modalContainer.current) + : null; +}; +export { Modal }; diff --git a/dist/components/multiselect/MultiSelect.component.d.ts b/dist/components/multiselect/MultiSelect.component.d.ts new file mode 100644 index 0000000000..c1668d1fd5 --- /dev/null +++ b/dist/components/multiselect/MultiSelect.component.d.ts @@ -0,0 +1,28 @@ +export type ItemProps = { + selected?: boolean; + label: string; + description?: string; + onSelect?: (arg0: any, arg1: any) => void; + onItemRemove?: (arg0: any, arg1: any) => void; +}; +export type OptionProps = { + label: string; + value: string | number; +}; +export type SearchProps = { + placeholder?: string; + options: Array; + onSelect: (arg0: any) => void; + onAdd?: (arg0: any) => void; + selectedOption: any; +}; +type MultiSelectProps = { + title?: string; + items: Array; + search?: SearchProps; + onItemRemove?: (arg0: any, arg1: any) => void; +}; +declare function MultiSelectList({ title, items, search, onItemRemove, }: MultiSelectProps): import("react/jsx-runtime").JSX.Element; +export declare const MultiSelect: typeof MultiSelectList; +export {}; +//# sourceMappingURL=MultiSelect.component.d.ts.map \ No newline at end of file diff --git a/dist/components/multiselect/MultiSelect.component.d.ts.map b/dist/components/multiselect/MultiSelect.component.d.ts.map new file mode 100644 index 0000000000..f91e168c33 --- /dev/null +++ b/dist/components/multiselect/MultiSelect.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MultiSelect.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/multiselect/MultiSelect.component.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAE1C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C,CAAC;AACF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB,CAAC;AACF,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAE5B,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAE9B,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC5B,cAAc,EAAE,GAAG,CAAC;CACrB,CAAC;AACF,KAAK,gBAAgB,GAAG;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C,CAAC;AAqGF,iBAAS,eAAe,CAAC,EACvB,KAAU,EACV,KAAU,EACV,MAAM,EACN,YAAY,GACb,EAAE,gBAAgB,2CAclB;AAED,eAAO,MAAM,WAAW,wBAAkB,CAAC"} \ No newline at end of file diff --git a/dist/components/multiselect/MultiSelect.component.js b/dist/components/multiselect/MultiSelect.component.js new file mode 100644 index 0000000000..908cc3d2aa --- /dev/null +++ b/dist/components/multiselect/MultiSelect.component.js @@ -0,0 +1,73 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, fontWeight } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { Icon } from '../icon/Icon.component'; +import { Button } from './../button/Button.component'; +import { Checkbox } from './../checkbox/Checkbox.component'; +import { Select } from './../select/Select.component'; +const MultiSelectContainer = styled.div ` + color: ${getThemePropSelector('textPrimary')}; +`; +const MultiSelectTitle = styled.h3 ` + padding: ${spacing.r16} 0; + margin: 0; + font-weight: ${fontWeight.bold}; + font-size: ${fontSize.large}; +`; +const MultiSelectItemContainer = styled.div ` + margin: ${spacing.r4} 0; + padding: ${spacing.r8} 0; + display: flex; + align-items: center; + border-bottom: 1px solid gray; + &:last-child { + border: none; + } +`; +const MultiSelectSearchContainer = styled.div ` + display: flex; + align-items: center; + .sc-select-container { + width: 100%; + } + .sc-button { + margin: 0 ${spacing.r8}; + } +`; +const MultiSelectItemLeft = styled.div ` + .sc-checkbox, + .sc-button { + margin: 0 ${spacing.r8}; + } +`; +const MultiSelectItemCenter = styled.div ` + display: flex; + flex-grow: 1; + align-items: center; + justify-content: space-between; +`; +const MultiSelectItemRight = styled.div ` + padding: 0 ${spacing.r16}; +`; +const MultiSelectItemLabel = styled.span ` + font-size: ${fontSize.large}; +`; +const MultiSelectItemDescription = styled.span ``; +function MultiSelectItem(props) { + const { selected, label, description, onItemRemove, onSelect } = props; + return (_jsxs(MultiSelectItemContainer, { className: "sc-multi-select-item", children: [_jsx(MultiSelectItemLeft, { className: "sc-multi-select-item-left", children: typeof selected === 'boolean' && onSelect && (_jsx(Checkbox, { checked: selected, onChange: (event) => onSelect(label, event) })) }), _jsxs(MultiSelectItemCenter, { className: "sc-multi-select-item-center", children: [_jsx(MultiSelectItemLabel, { className: "sc-multi-select-item-label", children: label }), description && (_jsx(MultiSelectItemDescription, { className: "sc-multi-select-item-description", children: description }))] }), _jsx(MultiSelectItemRight, { className: "sc-multi-select-item-right", children: onItemRemove && (_jsx(Button, { inverted: true, variant: "buttonDelete", onClick: (event) => onItemRemove(label, event), icon: _jsx(Icon, { name: "Delete" }) })) })] })); +} +function MultiSelectSearch(props) { + const { selectedOption, onSelect, onAdd, ...rest } = props; + return (_jsxs(MultiSelectSearchContainer, { className: "sc-multi-select-list-search", children: [_jsx(Select + // @ts-ignore + , { + // @ts-ignore + onChange: onSelect, value: selectedOption, ...rest }), onAdd && _jsx(Button, { onClick: onAdd, icon: _jsx(Icon, { name: "Create-add" }) })] })); +} +function MultiSelectList({ title = '', items = [], search, onItemRemove, }) { + return (_jsxs(MultiSelectContainer, { className: "sc-multi-select-list", children: [title && _jsx(MultiSelectTitle, { children: title }), search && _jsx(MultiSelectSearch, { ...search }), items.map((item, index) => (_jsx(MultiSelectItem, { onItemRemove: onItemRemove, ...item }, `sc-multi-select-item-${index}`)))] })); +} +export const MultiSelect = MultiSelectList; diff --git a/dist/components/navbar/Navbar.component.d.ts b/dist/components/navbar/Navbar.component.d.ts new file mode 100644 index 0000000000..1460c4cad9 --- /dev/null +++ b/dist/components/navbar/Navbar.component.d.ts @@ -0,0 +1,23 @@ +import { Item } from '../dropdown/Dropdown.component'; +type Action = { + type: string; + items?: Array; +}; +type Actions = Array; +type Tab = { + title?: string; + selected?: boolean; + onClick?: (arg0: any) => void; + link?: JSX.Element; + render?: JSX.Element; +}; +export type Props = { + onToggleClick?: () => void; + rightActions: Actions; + logo?: JSX.Element; + tabs?: Array; +}; +declare function NavBar({ onToggleClick, logo, tabs, rightActions, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare const Navbar: typeof NavBar; +export {}; +//# sourceMappingURL=Navbar.component.d.ts.map \ No newline at end of file diff --git a/dist/components/navbar/Navbar.component.d.ts.map b/dist/components/navbar/Navbar.component.d.ts.map new file mode 100644 index 0000000000..aa6888b0b6 --- /dev/null +++ b/dist/components/navbar/Navbar.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Navbar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/navbar/Navbar.component.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAY,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAGhE,KAAK,MAAM,GAAG;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;CACrB,CAAC;AACF,KAAK,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;AAC7B,KAAK,GAAG,GAAG;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAClB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;CACnB,CAAC;AA4JF,iBAAS,MAAM,CAAC,EACd,aAAa,EACb,IAAI,EACJ,IAAS,EACT,YAAiB,EACjB,GAAG,IAAI,EACR,EAAE,KAAK,2CAwDP;AAED,eAAO,MAAM,MAAM,eAAS,CAAC"} \ No newline at end of file diff --git a/dist/components/navbar/Navbar.component.js b/dist/components/navbar/Navbar.component.js new file mode 100644 index 0000000000..869e035ff9 --- /dev/null +++ b/dist/components/navbar/Navbar.component.js @@ -0,0 +1,169 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import React, { Fragment } from 'react'; +import styled, { css } from 'styled-components'; +import { Logo } from '../../icons/branding'; +import { spacing } from '../../spacing'; +import { fontSize, navbarHeight, navbarItemWidth } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { Dropdown } from '../dropdown/Dropdown.component'; +import { Icon } from '../icon/Icon.component'; +import { Button, FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +const NavbarContainer = styled.div ` + height: ${navbarHeight}; + display: flex; + justify-content: space-between; + ${css ` + background-color: ${getThemePropSelector('backgroundLevel1')}; + color: ${getThemePropSelector('textPrimary')}; + .fas, + .sc-trigger-text { + color: ${getThemePropSelector('textPrimary')}; + } + border-bottom: 0.5px solid ${(props) => props.theme.backgroundLevel3}; + box-sizing: border-box; + `}; +`; +const NavbarMenu = styled.div ` + display: flex; + justify-content: center; + align-items: center; +`; +const NavbarTabs = styled.div ` + flex: 1; + display: flex; + justify-content: flex-start; + align-items: center; + + a { + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; + height: 100%; + padding: 0 ${spacing.r16}; + border-bottom: ${spacing.r2} solid transparent; + border-top: ${spacing.r2} solid transparent; + ${(props) => { + const { selectedActive } = props.theme; + return css ` + color: ${getThemePropSelector('textPrimary')}; + &:hover { + background-color: ${getThemePropSelector('highlight')}; + } + &.selected { + color: ${getThemePropSelector('textPrimary')}; + font-weight: bold; + border-bottom-color: ${selectedActive}; + } + // :focus-visible is the keyboard-only version of :focus + &:focus-visible { + ${FocusVisibleStyle} + color: ${props.theme.textPrimary}; + } + `; +}}; + } +`; +const TabItem = styled.div ` + box-sizing: border-box; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + padding: 0 ${spacing.r16}; + ${(props) => { + const { textPrimary } = props.theme; + return css ` + color: ${textPrimary}; + &:hover { + border-bottom: ${spacing.r2} solid; + border-top: ${spacing.r2} solid; + cursor: pointer; + } + // :focus-visible is the keyboard-only version of :focus + &:focus-visible { + ${FocusVisibleStyle} + color: ${props.theme.textPrimary}; + } + `; +}}; + ${(props) => props.selected && + css ` + border-top: ${spacing.r2} solid; + border-bottom: ${spacing.r2} solid; + `}; +`; +const NavbarMenuItem = styled.div ` + display: flex; + justify-content: center; + align-items: center; + .sc-dropdown { + .trigger { + background-color: ${getThemePropSelector('backgroundLevel1')}; + &:hover { + background-color: ${getThemePropSelector('highlight')}; + } + height: ${navbarHeight}; + font-size: ${fontSize.base}; + } + .menu-item { + max-height: unset; + } + } + + .sc-button { + margin: 0; + border-radius: 0; + height: ${navbarHeight}; + font-size: ${fontSize.base}; + background-color: ${getThemePropSelector('backgroundLevel1')}; + &:hover { + background-color: ${getThemePropSelector('highlight')}; + } + // :focus-visible is the keyboard-only version of :focus + &:focus-visible { + ${FocusVisibleStyle} + color: ${(props) => props.theme.textPrimary}; + } + width: ${navbarItemWidth}; + } +`; +const LogoContainer = styled.div ` + display: flex; + justify-content: center; + align-items: center; + padding: 0 ${spacing.r16}; + svg { + width: 7.143rem; + height: 2.143rem; + } +`; +const getActionRenderer = ({ type, items = null, ...rest }, index) => { + if (type === 'dropdown') { + return items ? (_jsx(Dropdown, { size: "larger", variant: "backgroundLevel1", items: items, caret: false, ...rest }, `navbar_right_action_${index}`)) : null; + } + else if (type === 'button') { + return _jsx(Button, { ...rest }, `navbar_right_action_${index}`); + } + else if (type === 'custom') { + return _jsx(rest.render, {}, `navbar_right_action_${index}`); + } + return null; +}; +function NavBar({ onToggleClick, logo, tabs = [], rightActions = [], ...rest }) { + return (_jsxs(NavbarContainer, { className: "sc-navbar", ...rest, children: [_jsxs(NavbarMenu, { children: [onToggleClick && (_jsx(NavbarMenuItem, { onClick: onToggleClick, children: _jsx(Button, { icon: _jsx(Icon, { name: "Lat-menu" }), title: "Main Menu" }) })), _jsx(NavbarMenuItem, { children: _jsx(LogoContainer, { className: "sc-logo", children: logo ? logo : _jsx(Logo, {}) }) })] }), tabs.length ? (_jsx(NavbarTabs, { children: tabs.map(({ link, title, selected, onClick, render }, index) => { + if (render) { + return (_jsx(Fragment, { children: render }, `navbar_tab_item_${index}`)); + } + return link ? (React.cloneElement(link, { + className: selected ? 'selected' : '', + 'aria-selected': selected, + role: 'tab', + key: `navbar_tab_item_${index}`, + })) : (_jsx(TabItem, { onClick: onClick, role: "tab", selected: !!selected, "aria-selected": selected, children: _jsx("span", { children: title }) }, `navbar_tab_item_${index}`)); + }) })) : null, rightActions.length ? (_jsx(NavbarMenu, { children: _jsx(NavbarMenuItem, { children: rightActions.map((action, index) => + //@ts-ignore too costly to type this one now + getActionRenderer(action, index)) }) })) : null] })); +} +export const Navbar = NavBar; diff --git a/dist/components/notifications/Notification.component.d.ts b/dist/components/notifications/Notification.component.d.ts new file mode 100644 index 0000000000..6ab7bd44d7 --- /dev/null +++ b/dist/components/notifications/Notification.component.d.ts @@ -0,0 +1,12 @@ +import { Variant } from '../constants'; +export type Props = { + uid: string; + title: string; + message?: string; + variant?: Variant; + dismissAfter?: number; + onDismiss?: (arg0: string) => void; +}; +declare function Notification({ uid, title, message, variant, dismissAfter, onDismiss, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Notification }; +//# sourceMappingURL=Notification.component.d.ts.map \ No newline at end of file diff --git a/dist/components/notifications/Notification.component.d.ts.map b/dist/components/notifications/Notification.component.d.ts.map new file mode 100644 index 0000000000..5c4d68a378 --- /dev/null +++ b/dist/components/notifications/Notification.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Notification.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/notifications/Notification.component.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,MAAM,KAAK,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAkEF,iBAAS,YAAY,CAAC,EACpB,GAAG,EACH,KAAK,EACL,OAAO,EACP,OAAO,EACP,YAAY,EACZ,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CA8DP;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/notifications/Notification.component.js b/dist/components/notifications/Notification.component.js new file mode 100644 index 0000000000..ac12182d18 --- /dev/null +++ b/dist/components/notifications/Notification.component.js @@ -0,0 +1,107 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { darken } from 'polished'; +import { useEffect, useRef, useState } from 'react'; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontWeight, grayDarkest, black, white, grayLightest, } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { Icon } from '../icon/Icon.component'; +const NotificationContainer = styled.div ` + position: relative; + padding: ${spacing.r16}; + margin-top: ${spacing.r16}; + border-radius: 5px; + box-shadow: 0px 0px 3px ${grayDarkest}; + + ${(props) => { + var _a; + const variant = (_a = props.variant) !== null && _a !== void 0 ? _a : 'backgroundLevel1'; + const background = getThemePropSelector(variant)(props); + switch (props.variant) { + case 'warning': + return css ` + background-color: ${background}; + color: ${black}; + `; + case undefined: + return css ` + background-color: ${background}; + color: ${props.theme.textPrimary}; + `; + default: + return css ` + background-color: ${background}; + color: ${white}; + `; + } +}}; +`; +const NotificationTitle = styled.div ` + padding: 0 ${spacing.r16} ${spacing.r4} 0; + font-weight: ${fontWeight.bold}; +`; +const NotificationDismissProgress = styled.div ` + position: absolute; + bottom: 0; + left: 0; + height: 5px; + border-radius: 5px; + ${(props) => { + const variant = props.variant || 'backgroundLevel1'; + const background = getThemePropSelector(variant)(props); + const brandDark = darken(0.1, background); + return css ` + background-color: ${brandDark}; + width: ${(props.value / props.max) * 100}%; + transition: width 1s; + transition-timing-function: linear; + `; +}}; +`; +const NotificationClose = styled.div ` + position: absolute; + top: 15px; + right: 15px; + cursor: pointer; + &:hover { + color: ${grayLightest}; + } +`; +function Notification({ uid, title, message, variant, dismissAfter, onDismiss, ...rest }) { + const [dismissProgress, setDismissProgress] = useState(0); + const [timerId, setTimerId] = useState(undefined); + const dismissProgressRef = useRef(dismissProgress); + dismissProgressRef.current = dismissProgress; + useEffect(() => { + resumeTimer(); + }); + const clearTimer = () => { + if (dismissAfter) { + setTimerId(undefined); + clearTimeout(timerId); + } + }; + const resumeTimer = () => { + if (dismissAfter) { + if (dismissProgressRef.current === dismissAfter) { + dismiss(); + } + else if (!timerId) { + setTimerId( + //@ts-ignore node typing detected here instead of Dom one + setTimeout(() => { + setDismissProgress(dismissProgressRef.current + 1000); + resumeTimer(); + }, 1000)); + } + } + }; + const dismiss = () => { + if (timerId) { + clearTimer(); + } + onDismiss && onDismiss(uid); + }; + return (_jsxs(NotificationContainer, { className: "sc-notification", variant: variant, onMouseEnter: clearTimer, onMouseLeave: resumeTimer, ...rest, children: [_jsx(NotificationTitle, { children: title }), _jsx("div", { children: message }), !!dismissAfter && (_jsx(NotificationDismissProgress, { value: dismissProgress, max: dismissAfter, variant: variant })), _jsx(NotificationClose, { onClick: dismiss, children: _jsx(Icon, { name: "Close" }) })] })); +} +export { Notification }; diff --git a/dist/components/notifications/Notifications.component.d.ts b/dist/components/notifications/Notifications.component.d.ts new file mode 100644 index 0000000000..7b1168550d --- /dev/null +++ b/dist/components/notifications/Notifications.component.d.ts @@ -0,0 +1,14 @@ +import { Props as NotificationProps } from './Notification.component'; +export declare const TOP_LEFT = "tl"; +export declare const TOP_RIGHT = "tr"; +export declare const BOTTOM_LEFT = "bl"; +export declare const BOTTOM_RIGHT = "br"; +type Position = typeof TOP_LEFT | typeof TOP_RIGHT | typeof BOTTOM_LEFT | typeof BOTTOM_RIGHT; +type Props = { + position?: Position; + notifications: Array; + onDismiss: (arg0: string) => void; +}; +declare function Notifications({ position, notifications, onDismiss, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Notifications }; +//# sourceMappingURL=Notifications.component.d.ts.map \ No newline at end of file diff --git a/dist/components/notifications/Notifications.component.d.ts.map b/dist/components/notifications/Notifications.component.d.ts.map new file mode 100644 index 0000000000..92443f668c --- /dev/null +++ b/dist/components/notifications/Notifications.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Notifications.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/notifications/Notifications.component.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,IAAI,iBAAiB,EAC3B,MAAM,0BAA0B,CAAC;AAClC,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,SAAS,OAAO,CAAC;AAC9B,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,KAAK,QAAQ,GACT,OAAO,QAAQ,GACf,OAAO,SAAS,GAChB,OAAO,WAAW,GAClB,OAAO,YAAY,CAAC;AACxB,KAAK,KAAK,GAAG;IACX,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,aAAa,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAkCF,iBAAS,aAAa,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAgB5E;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/notifications/Notifications.component.js b/dist/components/notifications/Notifications.component.js new file mode 100644 index 0000000000..3b6de0a0df --- /dev/null +++ b/dist/components/notifications/Notifications.component.js @@ -0,0 +1,42 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { zIndex } from '../../style/theme'; +import { Notification, } from './Notification.component'; +export const TOP_LEFT = 'tl'; +export const TOP_RIGHT = 'tr'; +export const BOTTOM_LEFT = 'bl'; +export const BOTTOM_RIGHT = 'br'; +const NotificationsContainer = styled.div ` + position: fixed; + z-index: ${zIndex.notification}; + margin: ${spacing.r24}; + ${(props) => { + switch (props.position) { + case TOP_LEFT: + return css ` + top: 0; + left: 0; + `; + case BOTTOM_RIGHT: + return css ` + bottom: 0; + right: 0; + `; + case BOTTOM_LEFT: + return css ` + bottom: 0; + left: 0; + `; + default: + return css ` + top: 0; + right: 0; + `; + } +}}; +`; +function Notifications({ position, notifications, onDismiss, ...rest }) { + return (_jsx(NotificationsContainer, { className: "sc-notifications", position: position, ...rest, children: notifications.map((notification) => (_jsx(Notification, { ...notification, onDismiss: onDismiss }, notification.uid))) })); +} +export { Notifications }; diff --git a/dist/components/prettybytes/PrettyBytes.component.d.ts b/dist/components/prettybytes/PrettyBytes.component.d.ts new file mode 100644 index 0000000000..751726f488 --- /dev/null +++ b/dist/components/prettybytes/PrettyBytes.component.d.ts @@ -0,0 +1,8 @@ +type Props = { + bytes?: number | null; + decimals?: number | null; + unit?: 'iB' | 'B'; +}; +declare function PrettyBytes({ bytes, decimals, unit }: Props): import("react/jsx-runtime").JSX.Element; +export { PrettyBytes }; +//# sourceMappingURL=PrettyBytes.component.d.ts.map \ No newline at end of file diff --git a/dist/components/prettybytes/PrettyBytes.component.d.ts.map b/dist/components/prettybytes/PrettyBytes.component.d.ts.map new file mode 100644 index 0000000000..a51c17871a --- /dev/null +++ b/dist/components/prettybytes/PrettyBytes.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"PrettyBytes.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/prettybytes/PrettyBytes.component.tsx"],"names":[],"mappings":"AACA,KAAK,KAAK,GAAG;IACX,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC;CACnB,CAAC;AAEF,iBAAS,WAAW,CAAC,EAAE,KAAK,EAAE,QAAY,EAAE,IAAW,EAAE,EAAE,KAAK,2CA6B/D;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/prettybytes/PrettyBytes.component.js b/dist/components/prettybytes/PrettyBytes.component.js new file mode 100644 index 0000000000..9bfd12b861 --- /dev/null +++ b/dist/components/prettybytes/PrettyBytes.component.js @@ -0,0 +1,24 @@ +import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime"; +import prettyBytes from 'pretty-bytes'; +function PrettyBytes({ bytes, decimals = 0, unit = 'iB' }) { + if (bytes === undefined || bytes === null) + return _jsx(_Fragment, { children: "-" }); + let fractionDigits = decimals; + if (!Number.isFinite(decimals) || + (decimals !== undefined && decimals !== null && decimals < 0) || + bytes < 1024) + fractionDigits = 0; + if (!Number.isFinite(bytes) || !bytes || bytes < 0) + return bytes === Infinity || + bytes === -Infinity || + (bytes === 0 && !Object.is(bytes, -0)) ? (_jsx(_Fragment, { children: "0 B" })) : (_jsx(_Fragment, { children: "-" })); + return (_jsx(_Fragment, { children: prettyBytes(bytes, { + locale: 'en', + binary: unit === 'iB', + minimumFractionDigits: fractionDigits !== null && fractionDigits !== void 0 ? fractionDigits : undefined, + maximumFractionDigits: fractionDigits !== null && fractionDigits !== void 0 ? fractionDigits : undefined, + }) + .replace(/,/g, ' ') + .replace(/kiB/g, 'KiB') })); +} +export { PrettyBytes }; diff --git a/dist/components/progressbar/ProgressBar.component.d.ts b/dist/components/progressbar/ProgressBar.component.d.ts new file mode 100644 index 0000000000..8a5d2c01c3 --- /dev/null +++ b/dist/components/progressbar/ProgressBar.component.d.ts @@ -0,0 +1,17 @@ +import { Size } from '../constants'; +export type ProgressBarProps = { + percentage: number; + size?: Size | 'custom'; + color?: string; + backgroundColor?: string; + topLeftLabel?: string; + topRightLabel?: string; + bottomLeftLabel?: string; + bottomRightLabel?: string; + buildinLabel?: string; + isAnimation?: boolean; + height?: React.CSSProperties['height']; +}; +declare function ProgressBar({ percentage, size, color, backgroundColor, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel, buildinLabel, isAnimation, height, ...rest }: ProgressBarProps): import("react/jsx-runtime").JSX.Element; +export { ProgressBar }; +//# sourceMappingURL=ProgressBar.component.d.ts.map \ No newline at end of file diff --git a/dist/components/progressbar/ProgressBar.component.d.ts.map b/dist/components/progressbar/ProgressBar.component.d.ts.map new file mode 100644 index 0000000000..bf90bf2a5a --- /dev/null +++ b/dist/components/progressbar/ProgressBar.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ProgressBar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/progressbar/ProgressBar.component.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;CACxC,CAAC;AAiIF,iBAAS,WAAW,CAAC,EACnB,UAAe,EACf,IAAa,EACb,KAAK,EACL,eAAe,EACf,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,WAAmB,EACnB,MAAM,EACN,GAAG,IAAI,EACR,EAAE,gBAAgB,2CAqDlB;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/progressbar/ProgressBar.component.js b/dist/components/progressbar/ProgressBar.component.js new file mode 100644 index 0000000000..3f835f3e1c --- /dev/null +++ b/dist/components/progressbar/ProgressBar.component.js @@ -0,0 +1,129 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css, useTheme } from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, fontWeight } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +const Container = styled.div ``; +const ProgressBarContainer = styled.div ` + display: flex; + border-radius: 4px; + justify-content: space-between; + align-items: center; + + ${(props) => { + switch (props.size) { + case 'smaller': + return css ` + height: ${fontSize.smaller}; + font-size: ${fontSize.smaller}; + `; + case 'base': + return css ` + height: ${fontSize.small}; + font-size: ${fontSize.small}; + `; + case 'large': + return css ` + height: ${fontSize.base}; + font-size: ${fontSize.base}; + `; + case 'larger': + return css ` + height: 20px; + `; + case 'custom': + return css ` + height: ${props.height}; + font-size: ${props.height}; + `; + default: + return css ` + height: ${fontSize.base}; + font-size: ${fontSize.base}; + `; + } +}}; + + background-color: ${(props) => { + return props.backgroundColor; +}}; + /* Add the border for the progress bar when there is label inside.*/ + ${(props) => { + if (props.buildinLabel) { + return css ` + border: 1px solid; + border-color: ${getThemePropSelector('border')}; + `; + } +}}; +`; +const TopLeftLabel = styled.span ` + display: inline-block; + font-size: ${fontSize.large}; + font-weight: ${fontWeight.bold}; + color: ${getThemePropSelector('textPrimary')}; +`; +const TopRightLabel = styled.span ` + display: inline-block; + font-size: ${fontSize.small}; + color: ${getThemePropSelector('textPrimary')}; +`; +const BottomLabel = styled.span ` + display: inline-block; + color: ${getThemePropSelector('textSecondary')}; +`; +const TopLabelsContainer = styled.div ` + display: flex; + justify-content: space-between; + align-items: center; + margin: 0 0 ${spacing.r4} 0; +`; +const BottomLabelsContainer = styled(TopLabelsContainer) ` + margin: ${spacing.r4} 0 0 0; + font-size: ${fontSize.smaller}; +`; +const FilledAreaContainer = styled.div ` + display: flex; + justify-content: flex-start; + border-radius: 4px; + height: 100%; + ${(props) => { + if (props.isAnimation) { + return css ` + @keyframes widthAnimation { + from { + width: 0%; + } + to { + width: ${props.width} + "%"; + } + } + animation-duration: 1s; + animation-fill-mode: both; + animation-name: widthAnimation; + + background-color: ${props.color || props.theme.selectedActive} + width: ${props.width}%; + `; + } + else { + return css ` + background-color: ${props.color || props.theme.selectedActive}; + width: ${props.width}%; + `; + } +}} +`; +const BuildinLabel = styled.div ` + color: ${getThemePropSelector('textPrimary')}; + padding-left: 5px; + white-space: nowrap; +`; +function ProgressBar({ percentage = 50, size = 'base', color, backgroundColor, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel, buildinLabel, isAnimation = false, height, ...rest }) { + const theme = useTheme(); + if (!backgroundColor) { + backgroundColor = theme.backgroundLevel2; + } + return (_jsxs(Container, { className: "sc-progressbar", ...rest, children: [(topLeftLabel || topRightLabel) && (_jsxs(TopLabelsContainer, { children: [topLeftLabel && (_jsx(TopLeftLabel, { className: "sc-progressbar-topLeftLabel", children: topLeftLabel })), topRightLabel && (_jsx(TopRightLabel, { className: "sc-progressbar-toprightlabel", children: topRightLabel }))] })), _jsx(ProgressBarContainer, { className: "sc-progressbarcontainer", size: size, buildinLabel: buildinLabel, backgroundColor: backgroundColor, height: height, children: _jsx(FilledAreaContainer, { color: color, width: percentage, isAnimation: isAnimation, children: _jsx(BuildinLabel, { children: buildinLabel }) }) }), (bottomLeftLabel || bottomRightLabel) && (_jsxs(BottomLabelsContainer, { children: [bottomLeftLabel && (_jsx(BottomLabel, { className: "sc-progressbar-bottomleftlabel", children: bottomLeftLabel })), bottomRightLabel && (_jsx(BottomLabel, { className: "sc-progressbar-bottomrightlabel", children: bottomRightLabel }))] }))] })); +} +export { ProgressBar }; diff --git a/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts b/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts new file mode 100644 index 0000000000..bfd135e6c8 --- /dev/null +++ b/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts @@ -0,0 +1,7 @@ +import React from 'react'; +type Props = { + children: React.ReactNode; +}; +declare function ScrollbarWrapper({ children }: Props): import("react/jsx-runtime").JSX.Element; +export { ScrollbarWrapper }; +//# sourceMappingURL=ScrollbarWrapper.component.d.ts.map \ No newline at end of file diff --git a/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts.map b/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts.map new file mode 100644 index 0000000000..df5a4101b0 --- /dev/null +++ b/dist/components/scrollbarwrapper/ScrollbarWrapper.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ScrollbarWrapper.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/scrollbarwrapper/ScrollbarWrapper.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAmDF,iBAAS,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,2CAO5C;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/scrollbarwrapper/ScrollbarWrapper.component.js b/dist/components/scrollbarwrapper/ScrollbarWrapper.component.js new file mode 100644 index 0000000000..a204fc53c1 --- /dev/null +++ b/dist/components/scrollbarwrapper/ScrollbarWrapper.component.js @@ -0,0 +1,54 @@ +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; +import { createGlobalStyle, css } from 'styled-components'; +const GlobalStyle = createGlobalStyle ` +${(props) => { + const brand = props.theme; + return css ` + // Custom scrollbar + * { + // Chrome / Safari / Edge + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + ::-webkit-scrollbar-track { + background: ${brand.backgroundLevel3}; + } + + ::-webkit-scrollbar-thumb { + width: 4px; + height: 4px; + min-height: 20px; + background: ${brand.buttonSecondary}; + border-radius: 4px; + -webkit-border-radius: 4px; + background-clip: padding-box; + border: 2px solid rgba(0, 0, 0, 0); + } + + ::-webkit-scrollbar-thumb:vertical:hover, + ::-webkit-scrollbar-thumb:horizontal:hover { + background-color: rgba(89, 90, 120, 0.5); + } + + ::-webkit-scrollbar-button { + width: 0; + height: 0; + display: none; + } + ::-webkit-scrollbar-corner { + background-color: transparent; + } + + // Firefox + scrollbar-color: ${brand.buttonSecondary} ${brand.backgroundLevel3}; + scrollbar-width: thin; + } + `; +}} +`; +function ScrollbarWrapper({ children }) { + return (_jsxs(_Fragment, { children: [_jsx(GlobalStyle, {}), children] })); +} +export { ScrollbarWrapper }; diff --git a/dist/components/searchinput/SearchInput.component.d.ts b/dist/components/searchinput/SearchInput.component.d.ts new file mode 100644 index 0000000000..933487c4f6 --- /dev/null +++ b/dist/components/searchinput/SearchInput.component.d.ts @@ -0,0 +1,16 @@ +import React from 'react'; +import { ChangeEvent } from 'react'; +import { InputSize } from '../inputv2/inputv2'; +export type Props = { + placeholder?: string; + value: string; + onChange: (e: ChangeEvent) => void; + onReset?: () => void; + disabled?: boolean; + id?: string; + size?: InputSize; + autoComplete?: 'on' | 'off'; +}; +declare const SearchInput: React.ForwardRefExoticComponent>; +export { SearchInput }; +//# sourceMappingURL=SearchInput.component.d.ts.map \ No newline at end of file diff --git a/dist/components/searchinput/SearchInput.component.d.ts.map b/dist/components/searchinput/SearchInput.component.d.ts.map new file mode 100644 index 0000000000..3780c3c858 --- /dev/null +++ b/dist/components/searchinput/SearchInput.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SearchInput.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/searchinput/SearchInput.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAA2C,MAAM,OAAO,CAAC;AAG7E,OAAO,EAAS,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGtD,MAAM,MAAM,KAAK,GAAG;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,YAAY,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC;CAC7B,CAAC;AAuCF,QAAA,MAAM,WAAW,uEAuFhB,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/searchinput/SearchInput.component.js b/dist/components/searchinput/SearchInput.component.js new file mode 100644 index 0000000000..f7db2d81b6 --- /dev/null +++ b/dist/components/searchinput/SearchInput.component.js @@ -0,0 +1,77 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { forwardRef, useEffect, useRef, useState } from 'react'; +import styled, { css } from 'styled-components'; +import { Icon } from '../icon/Icon.component'; +import { Input } from '../inputv2/inputv2'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { spacing } from '../../spacing'; +const SearchInputContainer = styled.div ` + position: relative; + width: max-content; + + input[value] { + max-width: calc(100% - 1rem - ${spacing.f8} - 1rem); + } + + input[value=''] { + max-width: calc(100% - 1rem - ${spacing.f8}); + } + + ${(props) => { + if (props.disabled) { + return css ` + i { + opacity: 0.3; + cursor: not-allowed; + } + `; + } +}} + + //hide the default clear button in chrome + .search-box::-webkit-search-cancel-button { + display: none; + } +`; +const ClearButton = styled.div ` + position: absolute; + right: 1px; + top: 0px; +`; +const SearchInput = forwardRef(({ placeholder, value, onChange, onReset, disabled, id, size, autoComplete = 'on', ...rest }, forwardedRef) => { + const myInputRef = useRef(null); + const debounce = useRef(null); + const [debouncedValue, setDebouncedValue] = useState(value); + useEffect(() => { + return () => { + if (debounce.current) { + clearTimeout(debounce.current); + } + }; + }, []); + const reset = () => { + setDebouncedValue(''); + if (onReset) { + onReset(); + } + }; + const handleChange = (e) => { + setDebouncedValue(e.target.value); + if (debounce.current) { + clearTimeout(debounce.current); + } + debounce.current = setTimeout(() => { + onChange(e); + }, 300); + }; + return (_jsxs(SearchInputContainer, { className: "sc-searchinput", disabled: disabled, ...rest, children: [_jsx(Input, { autoComplete: autoComplete, min: '1', id: id || 'search', type: "search", "aria-label": "search", name: "search", placeholder: placeholder, value: debouncedValue, onChange: handleChange, onReset: reset, size: size, leftIcon: "Search", className: "search-box", disabled: disabled, ref: (element) => { + myInputRef.current = element; + if (typeof forwardedRef === 'function') { + forwardedRef(element); + } + else if (forwardedRef) { + forwardedRef.current = element; + } + } }), debouncedValue && (_jsx(ClearButton, { className: "close-icon", children: _jsx(Button, { icon: _jsx(Icon, { name: "Close" }), tooltip: { overlay: 'Reset' }, onClick: reset }) }))] })); +}); +export { SearchInput }; diff --git a/dist/components/select/Select.component.d.ts b/dist/components/select/Select.component.d.ts new file mode 100644 index 0000000000..69e17f2402 --- /dev/null +++ b/dist/components/select/Select.component.d.ts @@ -0,0 +1,14 @@ +export type Item = { + label: string; + value: string | number; +}; +type Items = Array; +type Props = { + id?: any; + options: Items; + formatOptionLabel?: (arg0: any) => JSX.Element; +}; +declare function SelectBox({ options, formatOptionLabel, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare const Select: typeof SelectBox; +export {}; +//# sourceMappingURL=Select.component.d.ts.map \ No newline at end of file diff --git a/dist/components/select/Select.component.d.ts.map b/dist/components/select/Select.component.d.ts.map new file mode 100644 index 0000000000..472f391fc7 --- /dev/null +++ b/dist/components/select/Select.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Select.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/select/Select.component.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,IAAI,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB,CAAC;AACF,KAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,KAAK,KAAK,GAAG;IACX,EAAE,CAAC,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,KAAK,CAAC;IACf,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC;CAChD,CAAC;AAqEF,iBAAS,SAAS,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAYhE;AAED,eAAO,MAAM,MAAM,kBAAY,CAAC"} \ No newline at end of file diff --git a/dist/components/select/Select.component.js b/dist/components/select/Select.component.js new file mode 100644 index 0000000000..bf134a9463 --- /dev/null +++ b/dist/components/select/Select.component.js @@ -0,0 +1,71 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import ReactSelect from 'react-select'; +import styled from 'styled-components'; +import { fontSize, fontWeight, gray, zIndex } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +const SelectContainer = styled.div ` + font-size: ${fontSize.base}; + .sc-select__control { + background-color: ${getThemePropSelector('backgroundLevel1')}; + border-radius: 4px; + border: 1px solid ${getThemePropSelector('border')}; + height: auto; + + .sc-select__placeholder, + .sc-select__single-value { + color: ${getThemePropSelector('textSecondary')}; + } + &.sc-select__control--is-focused { + border-color: ${getThemePropSelector('selectedActive')}; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), + 0 0 0 1px rgba(0, 126, 255, 0.1); + outline: none; + } + .sc-select__indicator { + color: ${getThemePropSelector('textSecondary')}; + &.sc-select__dropdown-indicator:hover { + color: ${getThemePropSelector('selectedActive')}; + } + &.sc-select__clear-indicator:hover { + color: ${gray}; + } + } + .sc-select__multi-value__remove { + border-radius: 0; + color: ${getThemePropSelector('textSecondary')}; + background-color: ${getThemePropSelector('backgroundLevel4')}; + &:hover { + color: ${gray}; + } + } + .sc-select__multi-value__label { + border-radius: 0; + color: ${getThemePropSelector('selectedActive')}; + background-color: ${getThemePropSelector('backgroundLevel4')}; + vertical-align: initial; + } + } + .sc-select__menu { + background-color: ${getThemePropSelector('backgroundLevel1')}; + color: ${getThemePropSelector('textSecondary')}; + border: 1px solid ${getThemePropSelector('selectedActive')}; + box-sizing: border-box; + overflow: hidden; + z-index: ${zIndex.dropdown}; + .sc-select__option { + &.sc-select__option--is-focused { + background-color: ${getThemePropSelector('backgroundLevel1')}; + } + &.sc-select__option--is-selected { + background-color: ${getThemePropSelector('backgroundLevel1')}; + color: ${getThemePropSelector('selectedActive')}; + font-weight: ${fontWeight.bold}; + } + } + } +`; +const defaultFormatOptionLabel = ({ label, ...rest }) => (_jsx("div", { className: "sc-select-option-label", ...rest, children: label })); +function SelectBox({ options, formatOptionLabel, ...rest }) { + return (_jsx(SelectContainer, { className: "sc-select-container", children: _jsx(ReactSelect, { className: "sc-select", classNamePrefix: "sc-select", options: options, formatOptionLabel: formatOptionLabel || defaultFormatOptionLabel, ...rest }) })); +} +export const Select = SelectBox; diff --git a/dist/components/selectv2/SelectStyle.d.ts b/dist/components/selectv2/SelectStyle.d.ts new file mode 100644 index 0000000000..7ab4e691ea --- /dev/null +++ b/dist/components/selectv2/SelectStyle.d.ts @@ -0,0 +1,3 @@ +declare const SelectStyle: import("styled-components").StyledComponent; +export { SelectStyle }; +//# sourceMappingURL=SelectStyle.d.ts.map \ No newline at end of file diff --git a/dist/components/selectv2/SelectStyle.d.ts.map b/dist/components/selectv2/SelectStyle.d.ts.map new file mode 100644 index 0000000000..c56eeeca74 --- /dev/null +++ b/dist/components/selectv2/SelectStyle.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SelectStyle.d.ts","sourceRoot":"","sources":["../../../src/lib/components/selectv2/SelectStyle.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,WAAW,sGAmQhB,CAAC;AACF,OAAO,EAAE,WAAW,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/selectv2/SelectStyle.js b/dist/components/selectv2/SelectStyle.js new file mode 100644 index 0000000000..59fc9deddb --- /dev/null +++ b/dist/components/selectv2/SelectStyle.js @@ -0,0 +1,238 @@ +import Select from 'react-select'; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, fontWeight, zIndex } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +const SelectStyle = styled(Select) ` + font-size: ${fontSize.base}; + box-sizing: border-box; + width: ${({ width }) => width}; + ${({ isDefault }) => isDefault ? `height: ${spacing.r32}` : `height: ${spacing.r24}`}; + + ${({ isDefault }) => !isDefault && `font-weight: ${fontWeight.bold};`} + .sc-select__control { + ${({ isDefault }) => isDefault ? `min-height: ${spacing.r32}` : `min-height: ${spacing.r24}`}; + padding-left: ${({ isDefault }) => (isDefault ? spacing.r8 : spacing.r16)}; + cursor: pointer; + + caret-color: ${({ isDefault }) => getThemePropSelector(isDefault ? 'textSecondary' : 'textPrimary')}; + background-color: ${({ isDefault }) => getThemePropSelector(isDefault ? 'backgroundLevel1' : 'selectedActive')}; + height: auto; + border-radius: ${({ isDefault }) => (isDefault ? spacing.r4 : spacing.r12)}; + border: ${spacing.r1} solid + ${({ isDefault }) => getThemePropSelector(isDefault ? 'border' : 'selectedActive')}; + + &:hover { + border: ${spacing.r1} solid + ${({ isDefault }) => getThemePropSelector(isDefault ? 'infoPrimary' : 'selectedActive')}; + ${({ isDefault }) => !isDefault && `background-color: ${getThemePropSelector('highlight')};`} + } + + &.sc-select__control--is-disabled { + pointer-events: auto; + cursor: not-allowed; + opacity: 0.5; + + &:hover { + border: ${spacing.r1} solid + ${({ isDefault }) => getThemePropSelector(isDefault ? 'border' : 'selectedActive')}; + } + } + + &.sc-select__control--menu-is-open { + ${(props) => props.isDefault + ? `background-color: ${props.theme.backgroundLevel1};` + : ` + border-radius: ${props.isMenuBottom + ? `${spacing.r12} ${spacing.r12} 0 0` + : `0 0 ${spacing.r12} ${spacing.r12}`}; + background-color: ${props.theme.selectedActive} !important; + `} + } + + &.sc-select__control--is-focused { + .sc-select__placeholder { + ${(props) => props.isSearchable && `opacity: 0.5;`} + } + ${(props) => props.isDefault + ? `border-color: ${props.theme.infoPrimary};` + : ` + border-color: ${props.theme.selectedActive}; + background-color: ${props.theme.highlight}; + `} + box-shadow: none; + outline: none; + } + + .sc-select__input { + ${({ isDefault }) => isDefault && `margin-top: ${spacing.r1};`} + color: ${getThemePropSelector('textPrimary')}; + + & > input { + font-weight: inherit; + font-family: inherit; + } + } + + .sc-select__placeholder { + font-style: italic; + color: ${getThemePropSelector('textSecondary')}; + } + + .sc-select__value-container { + ${({ isDefault }) => !isDefault && `max-height: ${spacing.r24};`} + padding: 0; + + input { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + opacity: 1 !important; + } + + .value-container-icon { + color: ${getThemePropSelector('textPrimary')}; + padding-right: ${spacing.r4}; + } + } + + .sc-select__single-value { + color: ${getThemePropSelector('textPrimary')}; + } + + .sc-select__indicator, + .sc-select__dropdown-indicator { + padding: 0 ${spacing.r8} 0 ${spacing.r8}; + color: ${({ isDefault }) => getThemePropSelector(isDefault ? 'textSecondary' : 'textPrimary')}; + } + } + + .sc-select__menu { + width: ${({ width }) => width}; + border: ${spacing.r1} solid + ${({ isDefault }) => getThemePropSelector(isDefault ? 'border' : 'selectedActive')}; + ${(props) => props.options && + props.options.length === 0 && + !props.isDefault && + ` + border: none; + `} + color: ${getThemePropSelector('textPrimary')}; + background-color: ${getThemePropSelector('backgroundLevel1')}; + box-sizing: border-box; + overflow: hidden; + margin: 0; + ${(props) => !props.isDefault && + ` + border-radius: ${props.isMenuBottom + ? `0 0 ${spacing.r12} ${spacing.r12}` + : `${spacing.r12} ${spacing.r12} 0 0`}; + `} + z-index: ${zIndex.dropdown}; + + .sc-select__menu-list { + padding: 0; + overflow: hidden; + ${({ isDefault }) => isDefault + ? ` + max-height: calc(${spacing.r32} * ${(props) => props.ITEMS_PER_SCROLL_WINDOW} + ${spacing.r32} / 2);` + : ` + max-height: calc(${spacing.r24} * ${(props) => props.ITEMS_PER_SCROLL_WINDOW} + ${spacing.r24} / 2);`} + + .sc-select__menu-notice { + color: ${({ isDefault }) => getThemePropSelector(isDefault ? 'textSecondary' : 'textPrimary')}; + &.sc-select__menu-notice--no-options { + background-color: ${({ isDefault }) => getThemePropSelector(isDefault ? 'backgroundLevel3' : 'selectedActive')}; + } + } + .sc-tooltip { + width: 100%; + } + + div > .react-window-option > .sc-select__option, + .sc-select__option { + cursor: pointer; + background-color: ${getThemePropSelector('backgroundLevel1')}; + height: ${({ isDefault }) => (isDefault ? spacing.r40 : spacing.r24)}; + display: flex; + align-items: center; + justify-content: space-between; + border: ${spacing.r1} solid transparent; + border-radius: 0; + ${(props) => props.isDefault && + `border-bottom: ${spacing.r1} solid ${props.theme.border};`} + padding-left: 0; + + .option-icon { + padding-right: ${spacing.r4}; + } + + &.sc-select__option--is-focused { + ${({ isDefault }) => isDefault && + `background-color: ${getThemePropSelector('backgroundLevel1')};`} + border: ${spacing.r1} dashed + ${getThemePropSelector('selectedActive')}; + } + + &.sc-select__option:hover { + border: ${spacing.r1} solid transparent; + background-color: ${getThemePropSelector('highlight')}; + } + + &.sc-select__option--is-disabled { + cursor: not-allowed; + opacity: 50%; + background-color: ${getThemePropSelector('backgroundLevel2')}; + font-style: italic; + i { + color: ${getThemePropSelector('textPrimary')}; + } + } + + &.sc-select__option--is-selected { + &:before { + content: ''; + background: ${getThemePropSelector('selectedActive')}; + position: absolute; + right: 0; + height: ${spacing.r24}; + width: ${spacing.r4}; + } + background-color: ${getThemePropSelector('highlight')}; + color: ${(props) => props.theme.textPrimary}; + } + + &.sc-select__option--is-disabled:hover { + opacity: 50%; + background-color: ${getThemePropSelector('backgroundLevel2')}; + } + + .sc-highlighted-matching-text { + color: ${getThemePropSelector('selectedActive')}; + } + + .option-value-wrapper { + display: flex; + align-items: center; + width: stretch; + padding: ${spacing.r4} ${spacing.r8} ${spacing.r4} ${spacing.r16}; + } + } + + ${({ isDefault }) => isDefault && + ` + div > .react-window-option:first-of-type > .sc-select__option { + .sc-select__option:first-of-type { + border-radius: ${spacing.r4} ${spacing.r4} 0 0; + } + + div > .react-window-option:last-of-type > .sc-select__option { + .sc-select__option:last-of-type { + border-bottom: ${spacing.r1} solid transparent; + border-radius: 0 0 ${spacing.r4} ${spacing.r4}; + } + `} + } + } +`; +export { SelectStyle }; diff --git a/dist/components/selectv2/Selectv2.component.d.ts b/dist/components/selectv2/Selectv2.component.d.ts new file mode 100644 index 0000000000..110a5367ce --- /dev/null +++ b/dist/components/selectv2/Selectv2.component.d.ts @@ -0,0 +1,32 @@ +import React from 'react'; +export type OptionProps = { + title?: string; + disabled?: boolean; + icon?: React.ReactNode; + children?: React.ReactNode; + value: string; + disabledReason?: React.ReactNode; +}; +export declare function Option({ value, children, disabled, icon, disabledReason, ...rest }: OptionProps): JSX.Element; +export type SelectProps = { + id: string; + placeholder?: string; + disabled?: boolean; + children?: React.ReactNode; + value?: string; + onFocus?: (event: FocusEvent) => void; + onBlur?: (event: FocusEvent) => void; + onChange: (newValue: string) => void; + variant?: 'default' | 'rounded'; + size?: '1' | '2/3' | '1/2' | '1/3'; + className?: string; + /** use menuPositon='fixed' inside modal to avoid display issue */ + menuPosition?: 'fixed' | 'absolute'; +}; +declare function SelectWithOptionContext(props: SelectProps): import("react/jsx-runtime").JSX.Element; +declare namespace SelectWithOptionContext { + var Option: typeof import("./Selectv2.component").Option; +} +export declare const Select: typeof SelectWithOptionContext; +export {}; +//# sourceMappingURL=Selectv2.component.d.ts.map \ No newline at end of file diff --git a/dist/components/selectv2/Selectv2.component.d.ts.map b/dist/components/selectv2/Selectv2.component.d.ts.map new file mode 100644 index 0000000000..89f9a3ee66 --- /dev/null +++ b/dist/components/selectv2/Selectv2.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Selectv2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/selectv2/Selectv2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAcf,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAClC,CAAC;AAkBF,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,GAAG,IAAI,EACR,EAAE,WAAW,GAAG,GAAG,CAAC,OAAO,CA0B3B;AAiOD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,IAAI,CAAC,EAAE,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CACrC,CAAC;AAgBF,iBAAS,uBAAuB,CAAC,KAAK,EAAE,WAAW,2CAyBlD;kBAzBQ,uBAAuB;;;AAyJhC,eAAO,MAAM,MAAM,gCAA0B,CAAC"} \ No newline at end of file diff --git a/dist/components/selectv2/Selectv2.component.js b/dist/components/selectv2/Selectv2.component.js new file mode 100644 index 0000000000..3e368cffcf --- /dev/null +++ b/dist/components/selectv2/Selectv2.component.js @@ -0,0 +1,266 @@ +import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { createContext, useContext, useState, useEffect, useRef, } from 'react'; +import { ScrollbarWrapper, Tooltip } from '../../index'; +import { components } from 'react-select'; +import { Icon } from '../icon/Icon.component'; +import { SelectStyle } from './SelectStyle'; +import { FixedSizeList as List } from 'react-window'; +import { convertRemToPixels } from '../../utils'; +import { spacing } from '../../spacing'; +import { convertSizeToRem } from '../inputv2/inputv2'; +import { ConstrainedText } from '../constrainedtext/Constrainedtext.component'; +const ITEMS_PER_SCROLL_WINDOW = 4; +// more/equal than NOPT_SEARCH options enable search +const NOPT_SEARCH = 8; +const usePreviousValue = (value) => { + const ref = useRef(null); + useEffect(() => { + ref.current = value; + }); + return ref.current; +}; +function useOptions() { + const optionContext = useContext(OptionContext); + if (!optionContext) + throw new Error('useOptions cannot be rendered outside the Select component'); + return Object.values(optionContext.options); +} +export function Option({ value, children, disabled, icon, disabledReason, ...rest }) { + const optionContext = useContext(OptionContext); + if (!optionContext) + throw new Error('Option cannot be rendered outside the Select component'); + const prevValue = usePreviousValue(value); + useEffect(() => { + if (prevValue && prevValue !== value) { + optionContext.unregister(prevValue); + } + optionContext.register({ + value: value, + label: children || '', + isDisabled: disabled || false, + icon: icon, + disabledReason: disabledReason, + optionProps: { ...rest }, + }); + return () => { + optionContext.unregister(value); + }; + //eslint-disable-next-line react-hooks/exhaustive-deps -- optionContext is mutable + }, [children, disabled, icon, value, prevValue]); + return _jsx(_Fragment, {}); +} +const Input = (props) => { + return _jsx(components.Input, { ...props }); +}; +const selectDropdownIndicator = (caretType, indicatorDirection) => { + if (caretType === 'chevron') { + if (indicatorDirection === 'up') + return 'Chevron-up'; + else + return 'Chevron-down'; + } + else { + if (indicatorDirection === 'up') + return 'Dropdown-up'; + else + return 'Dropdown-down'; + } +}; +const DropdownIndicator = (props) => { + const indicatorDirection = props.selectProps.menuIsOpen ? 'up' : 'down'; + const caretType = props.selectProps.isDefault ? 'chevron' : 'caret'; + return (_jsx(components.DropdownIndicator, { ...props, children: _jsx(Icon, { name: props.isDisabled + ? 'Deletion-marker' + : selectDropdownIndicator(caretType, indicatorDirection) }) })); +}; +const InternalOption = (width, isDefaultVariant) => (props) => { + const formatOptionLabel = () => { + const label = props.data.label; + const inputValue = props.selectProps.inputValue; + const parts = label + .split(inputValue) + .flatMap((item, index) => [inputValue, item]) + .slice(1); + const reducedWidth = `${parseFloat(width.replace('rem')) - 2}rem`; + if (inputValue) { + return (_jsx(ConstrainedText, { lineClamp: isDefaultVariant ? 2 : 1, tooltipStyle: { + width: reducedWidth, + }, text: parts.map((part, i) => { + const highlightStyle = part.toLowerCase() === inputValue.toLowerCase() + ? 'sc-highlighted-matching-text' + : ''; + return (_jsx("span", { role: highlightStyle ? 'mark' : undefined, className: highlightStyle, children: part }, i)); + }) })); + } + else { + return (_jsx(ConstrainedText, { lineClamp: isDefaultVariant ? 2 : 1, tooltipStyle: { + width: reducedWidth, + }, text: label })); + } + }; + const innerProps = { + ...props.innerProps, + ...props.data.optionProps, + // remove onMouseMove & onMouseOver so that options are not focused on hover + onMouseMove: undefined, + onMouseOver: undefined, + role: 'option', + 'aria-disabled': props.isDisabled, + 'aria-selected': props.isSelected, + }; + return (_jsx(Tooltip, { overlay: props.data.isDisabled && props.data.disabledReason, placement: "right", overlayStyle: { marginLeft: '0.5rem', maxWidth: '15rem' }, children: _jsxs(components.Option, { ...props, innerProps: innerProps, isFocused: props.isFocused && props.selectProps.keyboardFocusEnabled, children: [_jsxs("div", { className: "option-value-wrapper", children: [_jsx("div", { className: "option-icon", children: props.data.icon }), formatOptionLabel()] }), _jsx("div", { children: props.isDisabled && _jsx(Icon, { name: "Deletion-marker" }) })] }) })); +}; +const Menu = (props) => { + useEffect(() => { + props.selectProps.setIsMenuBottom(props.placement === 'bottom'); + }, [props]); + return _jsx(components.Menu, { ...props }); +}; +const getScrollOffset = (list, index, itemCount, offset) => { + const { itemSize, height } = list.props; + const scrollOffset = list.state ? list.state.scrollOffset : 0; + const lastItemOffset = Math.max(0, itemCount * itemSize - height); + const maxOffset = Math.min(lastItemOffset, index * itemSize); + const minOffset = Math.max(0, index * itemSize - height + itemSize); + if (scrollOffset >= minOffset && scrollOffset <= maxOffset) { + return scrollOffset; + } + else if (scrollOffset < minOffset) { + return minOffset === 0 ? minOffset : minOffset + offset; + } + else { + return maxOffset === 0 ? maxOffset : maxOffset - offset; + } +}; +const MenuList = (props) => { + const listRef = useRef(null); + const { children, getValue } = props; + const [selectedOption] = getValue(); + const optionHeight = convertRemToPixels(parseFloat(props.selectProps.isDefault ? spacing.r40 : spacing.r24)) || 32; + let selectedIndex = 0; + let focusedIndex = 0; + if (children && children.length > 0) { + selectedIndex = children.findIndex((child) => child.props.data === selectedOption); + focusedIndex = props.focusedOption + ? children.findIndex((child) => child.props.data === props.focusedOption) + : selectedIndex; + } + const initialOffset = selectedIndex * optionHeight - (ITEMS_PER_SCROLL_WINDOW - 1) * optionHeight; + useEffect(() => { + if (listRef && listRef.current) { + listRef.current.scrollTo(getScrollOffset(listRef.current, focusedIndex, children.length, optionHeight / 2)); + } + }, [children.length, focusedIndex, optionHeight, listRef]); + if (children.length > ITEMS_PER_SCROLL_WINDOW) { + return ( + // @ts-ignore + _jsx(List, { ref: listRef, className: "sc-select__menu-list", height: optionHeight * ITEMS_PER_SCROLL_WINDOW + optionHeight / 2, itemCount: children.length, itemSize: optionHeight, initialScrollOffset: initialOffset, + // css prop willChange used by react-window causes display issues with tooltip + style: { willChange: undefined }, children: ({ index, style }) => { + return (_jsx("div", { className: "react-window-option", style: style, children: children[index] })); + } })); + } + return _jsx(components.MenuList, { ...props, children: children }); +}; +const ValueContainer = ({ children, ...props }) => { + const selectedOption = props.selectProps.selectedOption; + const icon = selectedOption ? selectedOption.icon : null; + const ariaProps = { + innerProps: { + disabled: true, + role: props.selectProps.isSearchable ? 'combobox' : 'listbox', + 'aria-expanded': props.selectProps.menuIsOpen, + 'aria-autocomplete': 'list', + 'aria-label': props.selectProps.placeholder, + }, + }; + return (_jsxs(components.ValueContainer, { ...props, ...ariaProps, children: [icon ? _jsx("div", { className: "value-container-icon", children: icon }) : null, _jsx("div", { children: children })] })); +}; +const OptionContext = createContext(null); +function SelectWithOptionContext(props) { + const [options, setOptions] = useState({}); + const register = (option) => { + setOptions((prevOptions) => ({ + ...prevOptions, + [option.value]: option, + })); + }; + const unregister = (value) => { + setOptions((prevOptions) => { + const { [value]: _, ...rest } = prevOptions; + return rest; + }); + }; + return (_jsx(OptionContext.Provider, { value: { options, register, unregister }, children: _jsxs(_Fragment, { children: [_jsx(SelectBox, { ...props }), props.children] }) })); +} +function SelectBox({ placeholder = 'Select...', disabled = false, value, onChange, variant = 'default', className, size = '1', id, ...rest }) { + const [keyboardFocusEnabled, setKeyboardFocusEnabled] = useState(false); + const [searchSelection, setSearchSelection] = useState(''); + const [searchValue, setSearchValue] = useState(''); + const [customPlaceholder, setPlaceholder] = useState(placeholder); + const isDefaultVariant = variant === 'default'; + const [isMenuBottom, setIsMenuBottom] = useState(true); + const selectRef = useRef(); + const options = useOptions(); + const handleChange = (option) => { + const newValue = option ? option.value : ''; + if (onChange && typeof onChange === 'function' && newValue !== value) { + onChange(newValue); + } + if (options && options.length > NOPT_SEARCH) { + selectRef.current.blur(); + } + }; + const handleSearchInput = (inputValue, { action }) => { + if (options && options.length > NOPT_SEARCH) { + if (action === 'menu-close') { + setSearchSelection(''); + } + if (action === 'input-blur' || action === 'set-value') { + if (searchValue) + setPlaceholder(searchValue); + else + setPlaceholder(placeholder); + setSearchValue(inputValue); + } + else { + setSearchValue(inputValue); + if (inputValue.length === 0) + setPlaceholder(placeholder); + } + } + }; + const isEmptyStringInOptions = options.find((option) => option.value === ''); + // Force to reset the value + useEffect(() => { + if (!isEmptyStringInOptions && + value === '' && + selectRef.current && + selectRef.current.select) { + selectRef.current.select.clearValue(); + } + }, [value, selectRef, isEmptyStringInOptions]); + return (_jsx(ScrollbarWrapper, { children: _jsx(_Fragment, { children: options && (_jsx(SelectStyle, { inputId: id, className: ['sc-select', className].join(' '), classNamePrefix: "sc-select", name: "sc-select", value: searchSelection || options.find((opt) => opt.value === value), inputValue: options.length > NOPT_SEARCH ? searchValue : undefined, selectedOption: options.find((opt) => opt.value === value), keyboardFocusEnabled: keyboardFocusEnabled, options: options, isDisabled: disabled, placeholder: customPlaceholder, menuPlacement: "auto", isSearchable: options.length > NOPT_SEARCH, components: { + Input: Input, + Option: InternalOption(convertSizeToRem(size), isDefaultVariant), + Menu: Menu, + MenuList: MenuList, + ValueContainer: ValueContainer, + DropdownIndicator: DropdownIndicator, + IndicatorSeparator: null, + }, isDefault: isDefaultVariant, ITEMS_PER_SCROLL_WINDOW: ITEMS_PER_SCROLL_WINDOW, onChange: handleChange, onInputChange: handleSearchInput, ref: selectRef, isMenuBottom: isMenuBottom, setIsMenuBottom: setIsMenuBottom, onBlur: rest.onBlur, onFocus: rest.onFocus, onMenuClose: () => setKeyboardFocusEnabled(false), onKeyDown: (event) => { + if (event && + event.key === 'Enter' && + selectRef && + !selectRef.current.state.isOpen) { + selectRef.current.setState({ + menuIsOpen: true, + }); + } + else { + setKeyboardFocusEnabled(true); + } + }, width: convertSizeToRem(size), ...rest })) }) })); +} +SelectWithOptionContext.Option = Option; +export const Select = SelectWithOptionContext; diff --git a/dist/components/sidebar/Sidebar.component.d.ts b/dist/components/sidebar/Sidebar.component.d.ts new file mode 100644 index 0000000000..2c34408859 --- /dev/null +++ b/dist/components/sidebar/Sidebar.component.d.ts @@ -0,0 +1,21 @@ +type Item = { + label: string; + onClick: (arg0: any) => void; + active?: boolean; + icon?: JSX.Element; +}; +type Items = Array; +export type Props = { + expanded?: boolean; + actions: Items; + hoverable?: boolean; + onToggleClick?: () => void; +}; +export type WrapperProps = { + expanded?: boolean; + hoverable?: boolean; + hovered?: boolean; +}; +declare function Sidebar({ expanded, actions, onToggleClick, hoverable, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Sidebar }; +//# sourceMappingURL=Sidebar.component.d.ts.map \ No newline at end of file diff --git a/dist/components/sidebar/Sidebar.component.d.ts.map b/dist/components/sidebar/Sidebar.component.d.ts.map new file mode 100644 index 0000000000..7551ddab07 --- /dev/null +++ b/dist/components/sidebar/Sidebar.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Sidebar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/sidebar/Sidebar.component.tsx"],"names":[],"mappings":"AAaA,KAAK,IAAI,GAAG;IACV,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACpB,CAAC;AACF,KAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AACF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAyIF,iBAAS,OAAO,CAAC,EACf,QAAQ,EACR,OAAO,EACP,aAAa,EACb,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CA8DP;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/sidebar/Sidebar.component.js b/dist/components/sidebar/Sidebar.component.js new file mode 100644 index 0000000000..7f55fe7229 --- /dev/null +++ b/dist/components/sidebar/Sidebar.component.js @@ -0,0 +1,155 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { useState } from 'react'; +import styled, { css } from 'styled-components'; +import { fontSize, zIndex, sidebarWidth, sidebarItemHeight, } from '../../style/theme'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +import { spacing } from '../../spacing'; +import { FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +const Wrapper = styled.div ` + margin-top: 1px; + flex-shrink: 0; + ${(props) => { + const { backgroundLevel1, textPrimary } = props.theme; + return css ` + background-color: ${backgroundLevel1}; + color: ${textPrimary}; + .fas { + color: ${textPrimary}; + } + `; +}} + border-right: 1px solid ${(props) => props.theme.backgroundLevel3}; + ${(props) => { + if (props.expanded) { + return css ` + width: auto; + `; + } + return css ` + width: ${sidebarWidth}; + `; +}} + + ${(props) => { + const { backgroundLevel1 } = props.theme; + if (props.hoverable && props.hovered && !props.expanded) { + return css ` + .sc-sidebar { + position: relative; + width: fit-content; + height: 100%; + background-color: ${backgroundLevel1}; + z-index: ${zIndex.sidebar}; + border-right: 1px solid ${(props) => props.theme.backgroundLevel3}; + } + `; + } +}} +`; +const SidebarContainer = styled.div ` + ${(props) => { + const { backgroundLevel1 } = props.theme; + return css ` + background-color: ${backgroundLevel1}; + `; +}} + + ${(props) => { + if (props.expanded || + (props.hoverable && props.hovered && !props.expanded)) { + return css ` + width: auto; + `; + } + return css ` + width: ${sidebarWidth}; + `; +}} + + .sc-button { + border-radius: 0; + background-color: ${(props) => props.theme.backgroundLevel1}; + color: ${(props) => props.theme.textPrimary}; + &:hover { + background-color: ${(props) => props.theme.highlight}; + } + &:focus-visible { + ${FocusVisibleStyle} + } + height: ${sidebarItemHeight}; + width: ${sidebarWidth}; + padding: 0px; + } +`; +const SidebarItem = styled.div ` + position: relative; + display: flex; + align-items: center; + cursor: pointer; + justify-content: flex-start; + .fas { + font-size: ${fontSize.larger}; + } + + ${(props) => { + const { textPrimary, highlight } = props.theme; + return props.active + ? css ` + background-color: ${highlight}; + color: ${textPrimary}; + cursor: default; + &:focus-visible { + ${FocusVisibleStyle} + } + ` + : css ` + &:hover { + background-color: ${highlight}; + color: ${textPrimary}; + } + &:focus-visible { + ${FocusVisibleStyle} + } + &:active { + background-color: ${highlight}; + color: ${textPrimary}; + } + `; +}} +`; +const MenuItemText = styled.div ` + margin-right: ${spacing.r20}; +`; +// selected border-right +const MenuItemSelected = styled.div ` + position: absolute; + width: 3px; + height: 100%; + right: 0; + background-color: ${(props) => props.theme.selectedActive}; +`; +const MenuItemIcon = styled.div ` + width: ${sidebarWidth}; + display: flex; + justify-content: center; + align-items: center; + height: ${sidebarItemHeight}; +`; +function Sidebar({ expanded, actions, onToggleClick, hoverable, ...rest }) { + const [hovered, setHovered] = useState(false); + return (_jsx(Wrapper, { onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), hoverable: hoverable, hovered: hovered, expanded: expanded, children: _jsxs(SidebarContainer, { expanded: expanded, className: "sc-sidebar", hoverable: hoverable, hovered: hovered, ...rest, children: [onToggleClick && (_jsx(MenuItemIcon, { children: _jsx(Button, { icon: _jsx(Icon, { size: "lg", name: "Lat-menu" }), onClick: () => { + setHovered(false); + onToggleClick(); + } }) })), actions.map(({ active, label, onClick, icon = null, ...actionRest }, index) => { + return (_jsxs(SidebarItem, { className: "sc-sidebar-item", active: active, title: label, onClick: onClick, onKeyDown: (event) => { + if (event.key === ' ' || + event.key === 'Enter' || + event.key === 'Spacebar') { + event.preventDefault(); + onClick(event); + } + }, tabIndex: 0, ...actionRest, children: [!!icon && _jsx(MenuItemIcon, { children: icon }), (expanded || (hoverable && hovered)) && (_jsx(MenuItemText, { children: label })), active && _jsx(MenuItemSelected, {})] }, index)); + })] }) })); +} +export { Sidebar }; diff --git a/dist/components/spacedbox/SpacedBox.d.ts b/dist/components/spacedbox/SpacedBox.d.ts new file mode 100644 index 0000000000..dc3919a79e --- /dev/null +++ b/dist/components/spacedbox/SpacedBox.d.ts @@ -0,0 +1,34 @@ +type SpacingValue = 0 | 1 | 2 | 4 | 8 | 12 | 14 | 16 | 20 | 24 | 28 | 32; +export type Props = { + m?: SpacingValue; + mt?: SpacingValue; + mr?: SpacingValue; + mb?: SpacingValue; + ml?: SpacingValue; + mx?: SpacingValue; + my?: SpacingValue; + p?: SpacingValue; + pt?: SpacingValue; + pr?: SpacingValue; + pb?: SpacingValue; + pl?: SpacingValue; + px?: SpacingValue; + py?: SpacingValue; +}; +/** + * @deprecated + * Please use Box with import { Box } from '@scality/core-ui/dist/next'; + * + * Most common use cases: + * + * `` + * + * `` + * + * Props : m, mt, mr, mb, ml, mx, my, p, pt, pr, pb, pl, px, py + * + * Values: 0, 1, 2, 4, 8, 12, 14, 16, 20, 24, 28, 32 + */ +declare const SpacedBox: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, Props, never>; +export { SpacedBox }; +//# sourceMappingURL=SpacedBox.d.ts.map \ No newline at end of file diff --git a/dist/components/spacedbox/SpacedBox.d.ts.map b/dist/components/spacedbox/SpacedBox.d.ts.map new file mode 100644 index 0000000000..b026ba6573 --- /dev/null +++ b/dist/components/spacedbox/SpacedBox.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SpacedBox.d.ts","sourceRoot":"","sources":["../../../src/lib/components/spacedbox/SpacedBox.ts"],"names":[],"mappings":"AAEA,KAAK,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACzE,MAAM,MAAM,KAAK,GAAG;IAClB,CAAC,CAAC,EAAE,YAAY,CAAC;IACjB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,CAAC,CAAC,EAAE,YAAY,CAAC;IACjB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,EAAE,CAAC,EAAE,YAAY,CAAC;CACnB,CAAC;AAmEF;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,SAAS,4GAed,CAAC;AACF,OAAO,EAAE,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/spacedbox/SpacedBox.js b/dist/components/spacedbox/SpacedBox.js new file mode 100644 index 0000000000..cc1559a5d2 --- /dev/null +++ b/dist/components/spacedbox/SpacedBox.js @@ -0,0 +1,64 @@ +import styled from 'styled-components'; +import { spacing } from '../../style/theme'; +const validValue = [0, 1, 2, 4, 8, 12, 14, 16, 20, 24, 28, 32]; +const createSpacingFn = (propsName, spacingFields) => (props) => { + if (!props[propsName] && props[propsName] !== 0) { + return null; + } + //@ts-ignore -- this is ensured below + let value = props[propsName]; + if (!validValue.includes(value)) { + console.warn(`'${propsName}' props should be a number in this list: ` + + '0, 1, 2, 4, 8, 12, 14, 16, 20, 24, 28, 32'); + return null; + } + const result = spacingFields + .map((param) => `${param}: ${spacing[`sp${value}`]}`) + .join(';'); + return result; +}; +const m = createSpacingFn('m', ['margin']); +const mt = createSpacingFn('mt', ['margin-top']); +const mr = createSpacingFn('mr', ['margin-right']); +const mb = createSpacingFn('mb', ['margin-bottom']); +const ml = createSpacingFn('ml', ['margin-left']); +const mx = createSpacingFn('mx', ['margin-left', 'margin-right']); +const my = createSpacingFn('my', ['margin-top', 'margin-bottom']); +const p = createSpacingFn('p', ['padding']); +const pt = createSpacingFn('pt', ['padding-top']); +const pr = createSpacingFn('pr', ['padding-right']); +const pb = createSpacingFn('pb', ['padding-bottom']); +const pl = createSpacingFn('pl', ['padding-left']); +const px = createSpacingFn('px', ['padding-left', 'padding-right']); +const py = createSpacingFn('py', ['padding-top', 'padding-bottom']); +/** + * @deprecated + * Please use Box with import { Box } from '@scality/core-ui/dist/next'; + * + * Most common use cases: + * + * `` + * + * `` + * + * Props : m, mt, mr, mb, ml, mx, my, p, pt, pr, pb, pl, px, py + * + * Values: 0, 1, 2, 4, 8, 12, 14, 16, 20, 24, 28, 32 + */ +const SpacedBox = styled.div ` + ${m}; + ${mt}; + ${mr}; + ${mb}; + ${ml}; + ${mx}; + ${my}; + ${p}; + ${pt}; + ${pr}; + ${pb}; + ${pl}; + ${px}; + ${py}; +`; +export { SpacedBox }; diff --git a/dist/components/sparkline/SparkLine.component.d.ts b/dist/components/sparkline/SparkLine.component.d.ts new file mode 100644 index 0000000000..c6dea0e883 --- /dev/null +++ b/dist/components/sparkline/SparkLine.component.d.ts @@ -0,0 +1,18 @@ +type Props = { + id: string; + title?: string; + width?: number; + height?: number; + data: Array>; + xAxis: Record; + yAxis: Record; + row: Record; + lineConfig?: Record; + sparkLineColor?: string; + upTrendColor?: string; + bottomTrendColor?: string; +}; +declare function SparkLine({ id, title, width, height, data, xAxis, yAxis, row, lineConfig, sparkLineColor, upTrendColor, bottomTrendColor, }: Props): import("react/jsx-runtime").JSX.Element; +export declare const Sparkline: typeof SparkLine; +export {}; +//# sourceMappingURL=SparkLine.component.d.ts.map \ No newline at end of file diff --git a/dist/components/sparkline/SparkLine.component.d.ts.map b/dist/components/sparkline/SparkLine.component.d.ts.map new file mode 100644 index 0000000000..d05ef34c81 --- /dev/null +++ b/dist/components/sparkline/SparkLine.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SparkLine.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/sparkline/SparkLine.component.tsx"],"names":[],"mappings":"AAEA,KAAK,KAAK,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,iBAAS,SAAS,CAAC,EACjB,EAAE,EACF,KAAK,EACL,KAAW,EACX,MAAW,EACX,IAAI,EACJ,KAAK,EACL,KAAK,EACL,GAAG,EACH,UAAU,EACV,cAAc,EACd,YAA2B,EAC3B,gBAAwB,GACzB,EAAE,KAAK,2CA+IP;AAED,eAAO,MAAM,SAAS,kBAAY,CAAC"} \ No newline at end of file diff --git a/dist/components/sparkline/SparkLine.component.js b/dist/components/sparkline/SparkLine.component.js new file mode 100644 index 0000000000..fb5fb24df5 --- /dev/null +++ b/dist/components/sparkline/SparkLine.component.js @@ -0,0 +1,148 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { VegaChart } from '../vegachart/VegaChart.component'; +import { yellowOrange, green } from '../../style/theme'; +function SparkLine({ id, title, width = 300, height = 80, data, xAxis, yAxis, row, lineConfig, sparkLineColor, upTrendColor = yellowOrange, bottomTrendColor = green, }) { + const spec = { + title: { + text: title, + }, + data: { + values: data, + }, + facet: { + row, + }, + spec: { + width, + height, + layer: [ + // display the sparkline chart + { + mark: { + type: 'line', + ...lineConfig, + }, + encoding: { + x: xAxis, + y: yAxis, + color: { + value: sparkLineColor, + }, + }, + }, // display the label to specify the max/min data + { + mark: { + type: 'text', + style: 'labelMin', + align: 'bottom', + dy: height / 2, + dx: width / 2 + 10, + }, + encoding: { + text: { + aggregate: 'min', + field: 'y', + type: 'quantitative', + }, + }, + }, + { + mark: { + type: 'text', + style: 'labelMax', + align: 'top', + dy: -(height / 2), + dx: width / 2 + 10, + }, + encoding: { + text: { + aggregate: 'max', + field: 'y', + type: 'quantitative', + }, + }, + }, // display the up and bottom trend line + { + mark: { + type: 'rule', + style: 'ruleMaxEnd', + color: upTrendColor, + }, + encoding: { + y: { + aggregate: 'max', + field: 'y', + type: 'quantitative', + }, + x: { + value: width - 15, + }, + x2: { + value: width, + }, + }, + }, + { + mark: { + type: 'rule', + style: 'ruleMaxStart', + color: upTrendColor, + opacity: 0.1, + }, + encoding: { + y: { + aggregate: 'max', + field: 'y', + type: 'quantitative', + }, + x: { + value: 0, + }, + x2: { + value: width - 15, + }, + }, + }, + { + mark: { + type: 'rule', + style: 'ruleMinEnd', + color: bottomTrendColor, + }, + encoding: { + y: { + value: height, + }, + x: { + value: width - 15, + }, + x2: { + value: width, + }, + }, + }, + { + mark: { + type: 'rule', + style: 'ruleMinStart', + color: bottomTrendColor, + opacity: 0.1, + }, + encoding: { + y: { + value: height, + }, + x: { + value: 0, + }, + x2: { + value: width - 15, + }, + }, + }, + ], + }, + }; + return _jsx(VegaChart, { className: "sc-sparkline", id: id, spec: spec }); +} +export const Sparkline = SparkLine; diff --git a/dist/components/statuswrapper/Statuswrapper.component.d.ts b/dist/components/statuswrapper/Statuswrapper.component.d.ts new file mode 100644 index 0000000000..ac796475ea --- /dev/null +++ b/dist/components/statuswrapper/Statuswrapper.component.d.ts @@ -0,0 +1,9 @@ +import * as React from 'react'; +import { Status } from '../constants'; +type Props = { + status: Status; + children: React.ReactNode; +}; +declare function StatusWrapper({ status, children }: Props): import("react/jsx-runtime").JSX.Element; +export { StatusWrapper }; +//# sourceMappingURL=Statuswrapper.component.d.ts.map \ No newline at end of file diff --git a/dist/components/statuswrapper/Statuswrapper.component.d.ts.map b/dist/components/statuswrapper/Statuswrapper.component.d.ts.map new file mode 100644 index 0000000000..e3fe23beaf --- /dev/null +++ b/dist/components/statuswrapper/Statuswrapper.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Statuswrapper.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/statuswrapper/Statuswrapper.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EACL,MAAM,EAKP,MAAM,cAAc,CAAC;AA8CtB,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,iBAAS,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,2CAQjD;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/statuswrapper/Statuswrapper.component.js b/dist/components/statuswrapper/Statuswrapper.component.js new file mode 100644 index 0000000000..62d334337a --- /dev/null +++ b/dist/components/statuswrapper/Statuswrapper.component.js @@ -0,0 +1,44 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { STATUS_CRITICAL, STATUS_UNKNOWN, STATUS_WARNING, } from '../constants'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faQuestionCircle, faExclamationCircle, faTimesCircle, } from '@fortawesome/free-solid-svg-icons'; +const BadgeWrapper = styled.span ` + height: fit-content; + width: fit-content; + position: relative; + margin-right: 0.5rem; + display: inline-block; +`; +const BadgeStyled = styled(FontAwesomeIcon) ` + ${(props) => { + const theme = props.theme; + return css ` + background: ${theme.backgroundLevel1}; + border-radius: 50%; + color: ${theme.textSecondary}; + position: absolute; + top: -25%; + right: -35%; + transform: scale(0.5); + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.25); + `; +}} +`; +const getBadgeIcon = (status) => { + switch (status) { + case STATUS_WARNING: + return faExclamationCircle; + case STATUS_CRITICAL: + return faTimesCircle; + case STATUS_UNKNOWN: + return faQuestionCircle; + default: + return null; + } +}; +function StatusWrapper({ status, children }) { + const icon = getBadgeIcon(status); + return (_jsxs(BadgeWrapper, { children: [children, icon !== null && _jsx(BadgeStyled, { icon: icon })] })); +} +export { StatusWrapper }; diff --git a/dist/components/steppers/Stepper.component.d.ts b/dist/components/steppers/Stepper.component.d.ts new file mode 100644 index 0000000000..f8ef72fbb5 --- /dev/null +++ b/dist/components/steppers/Stepper.component.d.ts @@ -0,0 +1,12 @@ +export interface StepperContextType { + next: (props: Record) => void; + prev: (props: Record) => void; +} +declare global { + interface Window { + StepperContext: React.Context; + } +} +export declare const useStepper: UseStepper; +export declare const Stepper: Stepper; +//# sourceMappingURL=Stepper.component.d.ts.map \ No newline at end of file diff --git a/dist/components/steppers/Stepper.component.d.ts.map b/dist/components/steppers/Stepper.component.d.ts.map new file mode 100644 index 0000000000..96116ccce6 --- /dev/null +++ b/dist/components/steppers/Stepper.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Stepper.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/steppers/Stepper.component.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC/C,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAChD;AACD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;KAC1D;CACF;AAMD,eAAO,MAAM,UAAU,EAAE,UASxB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,OAgCrB,CAAC"} \ No newline at end of file diff --git a/dist/components/steppers/Stepper.component.js b/dist/components/steppers/Stepper.component.js new file mode 100644 index 0000000000..cff034af69 --- /dev/null +++ b/dist/components/steppers/Stepper.component.js @@ -0,0 +1,33 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +/// +import { createContext, useContext, useState } from 'react'; +import { Steppers } from './Steppers.component'; +import { Box } from '../box/Box'; +if (!window.StepperContext) { + window.StepperContext = createContext(null); +} +//@ts-ignore +export const useStepper = (index, steps) => { + const context = useContext(window.StepperContext); + if (context === null) { + throw new Error('Cannot use useStepper outside of Stepper'); + } + const { next, prev } = context; + return { next, prev }; +}; +export const Stepper = ({ steps }) => { + const [stepProps, setStepProps] = useState({ step: 0, props: {} }); + const next = (props) => { + setStepProps({ step: stepProps.step + 1, props }); + }; + const prev = (props) => { + setStepProps({ step: stepProps.step - 1, props }); + }; + const { Component } = steps[stepProps.step]; + const StepperContext = window.StepperContext; + return (_jsx(StepperContext.Provider, { value: { next, prev }, children: _jsxs(Box, { display: "flex", gap: 32, flex: 1, height: "100%", children: [_jsx(Steppers, { activeStep: stepProps.step, steps: steps.map((step) => { + return { + title: step.label, + }; + }) }), _jsx(Component, { ...stepProps.props })] }) })); +}; diff --git a/dist/components/steppers/Steppers.component.d.ts b/dist/components/steppers/Steppers.component.d.ts new file mode 100644 index 0000000000..cc3512115e --- /dev/null +++ b/dist/components/steppers/Steppers.component.d.ts @@ -0,0 +1,17 @@ +type StepProps = { + title: React.ReactNode; + content?: React.ReactNode; + active?: boolean; + completed?: boolean; + isLast?: boolean; + index?: number; + error?: boolean; + inProgress?: boolean; +}; +type Props = { + steps: Array; + activeStep: number; +}; +declare function Steppers({ steps, activeStep, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Steppers }; +//# sourceMappingURL=Steppers.component.d.ts.map \ No newline at end of file diff --git a/dist/components/steppers/Steppers.component.d.ts.map b/dist/components/steppers/Steppers.component.d.ts.map new file mode 100644 index 0000000000..3b3b9574d1 --- /dev/null +++ b/dist/components/steppers/Steppers.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Steppers.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/steppers/Steppers.component.tsx"],"names":[],"mappings":"AAMA,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AACF,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAgIF,iBAAS,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAiBtD;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/steppers/Steppers.component.js b/dist/components/steppers/Steppers.component.js new file mode 100644 index 0000000000..a6ec0f1856 --- /dev/null +++ b/dist/components/steppers/Steppers.component.js @@ -0,0 +1,102 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +import { gray, white } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +import { Icon } from '../icon/Icon.component'; +import { Loader } from '../loader/Loader.component'; +const SteppersContainer = styled.div ` + padding-top: 4rem; + padding-left: 2rem; +`; +const StepContainer = styled.div ` + display: flex; + min-height: 50px; + min-width: 20rem; +`; +const Panel = styled.div ` + display: flex; + flex-direction: column; +`; +const Circle = styled.div ` + display: flex; + justify-content: center; + align-items: center; + line-height: 30px; + width: 30px; + height: 30px; + border-radius: 50%; + + ${(props) => { + const { statusCritical, statusHealthy, selectedActive, buttonSecondary } = props.theme; + if (props.error) { + return css ` + background-color: ${statusCritical}; + color: ${white}; + `; + } + else if (props.active) { + return css ` + background-color: ${selectedActive}; + color: ${white}; + svg { + fill: ${white}; + } + `; + } + else if (props.completed) { + return css ` + background-color: ${statusHealthy}; + color: ${white}; + `; + } + else { + return css ` + background-color: ${buttonSecondary}; + color: ${white}; + `; + } +}}; +`; +const StepHeader = styled.span ` + margin-left: ${spacing.r8}; + line-height: 30px; + color: ${(props) => props.active + ? getThemePropSelector('textPrimary') + : getThemePropSelector('textSecondary')}; +`; +const StepContent = styled.div ` + padding: ${spacing.r8} 0 ${spacing.r8} ${spacing.r8}; +`; +const BottomBar = styled.hr ` + flex-grow: 1; + margin: 0; + border: none; + margin: 4px 14px; + + ${(props) => { + if (props.completed) { + return css ` + border-left: 2px solid ${props.theme.statusHealthy}; + `; + } + else { + return css ` + border-left: 2px solid ${gray}; + `; + } +}}; +`; +function Step(props) { + const { title, content, active, completed, isLast, index = 0, error, inProgress, } = props; + const circleContent = completed ? _jsx(Icon, { name: "Check" }) : index + 1; + return (_jsxs(StepContainer, { children: [_jsxs(Panel, { children: [_jsx(Circle, { active: active, error: error, completed: completed, children: active && inProgress ? (_jsx(Loader, { size: "base" })) : (_jsx("span", { children: circleContent })) }), !isLast && _jsx(BottomBar, { completed: completed })] }), _jsxs(Panel, { children: [_jsx("div", { style: { + height: '30px', + display: 'flex', + alignItems: 'center', + }, children: _jsx(StepHeader, { active: active, children: title }) }), active && _jsx(StepContent, { children: content })] })] })); +} +function Steppers({ steps, activeStep, ...rest }) { + return (_jsx(SteppersContainer, { className: "sc-steppers", ...rest, children: steps.map(({ title, content, ...stepRest }, index) => (_jsx(Step, { title: title, content: content, active: index === activeStep, completed: index < activeStep, isLast: index === steps.length - 1, index: index, ...stepRest }, index))) })); +} +export { Steppers }; diff --git a/dist/components/tablev2/MultiSelectableContent.d.ts b/dist/components/tablev2/MultiSelectableContent.d.ts new file mode 100644 index 0000000000..d33f0cf8e4 --- /dev/null +++ b/dist/components/tablev2/MultiSelectableContent.d.ts @@ -0,0 +1,20 @@ +import { Row } from 'react-table'; +import { TableHeightKeyType, TableLocalType, TableVariantType } from './TableUtils'; +type MultiSelectableContentProps = Record> = { + onMultiSelectionChanged?: (rows: Row[]) => void; + onSingleRowSelected?: (row: Row) => void; + onToggleAll?: (selected: boolean) => void; + rowHeight?: TableHeightKeyType; + separationLineVariant?: TableVariantType; + locale?: TableLocalType; + customItemKey?: (index: number, data: DATA_ROW) => string; + hasScrollbar?: boolean; + isLoadingMoreItems?: boolean; + children?: (rows: JSX.Element) => JSX.Element; +}; +/** + * FIXME Need to spend time to change the type to something like this + */ +export declare const MultiSelectableContent: = Record>({ onMultiSelectionChanged, onSingleRowSelected, onToggleAll, rowHeight, separationLineVariant, locale, customItemKey, isLoadingMoreItems, children, }: MultiSelectableContentProps) => import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=MultiSelectableContent.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/MultiSelectableContent.d.ts.map b/dist/components/tablev2/MultiSelectableContent.d.ts.map new file mode 100644 index 0000000000..e076f5205f --- /dev/null +++ b/dist/components/tablev2/MultiSelectableContent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MultiSelectableContent.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/MultiSelectableContent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAUlC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAOtB,KAAK,2BAA2B,CAC9B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,IAAI,CAAC;IAC1D,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IACnD,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,qBAAqB,CAAC,EAAE,gBAAgB,CAAC;IAEzC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;CAC/C,CAAC;AAEF;;GAEG;AAaH,eAAO,MAAM,sBAAsB,GACjC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,mLAYvC,2BAA2B,CAAC,QAAQ,CAAC,4CAyNvC,CAAC"} \ No newline at end of file diff --git a/dist/components/tablev2/MultiSelectableContent.js b/dist/components/tablev2/MultiSelectableContent.js new file mode 100644 index 0000000000..4d45dd70af --- /dev/null +++ b/dist/components/tablev2/MultiSelectableContent.js @@ -0,0 +1,123 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { useEffect, memo } from 'react'; +import { areEqual } from 'react-window'; +import { useTableContext } from './Tablev2.component'; +import { HeadRow, SortCaret, TableBody, TableHeader, TableRowMultiSelectable, } from './Tablestyle'; +import { TableRows, useTableScrollbar } from './TableCommon'; +import useSyncedScroll from './useSyncedScroll'; +import { Box } from '../box/Box'; +import { Loader } from '../loader/Loader.component'; +import { spacing } from '../../spacing'; +/** + * FIXME Need to spend time to change the type to something like this + */ +// type MultiSelectableContentProps> = { +// onMultiSelectionChanged: (rows: Row[]) => void; +// rowHeight?: TableHeightKeyType; +// separationLineVariant?: TableVariantType; +// customItemKey?: (index: Number, data: ENTRY) => string; +// } & ({ +// locale: TableLocalType; +// } | { +// children: (rows: JSX.Element) => JSX.Element; +// }); +export const MultiSelectableContent = ({ onMultiSelectionChanged, onSingleRowSelected, onToggleAll, rowHeight = 'h40', separationLineVariant = 'backgroundLevel3', locale = 'en', customItemKey, isLoadingMoreItems, children, }) => { + const { headerGroups, prepareRow, rows, setRowHeight, setHiddenColumns, selectedRowIds, isAllRowsSelected, toggleAllRowsSelected, } = useTableContext(); + useEffect(() => { + setRowHeight(rowHeight); + }, [rowHeight, setRowHeight]); + useEffect(() => { + setHiddenColumns((oldHiddenColumns) => { + return oldHiddenColumns.filter((column) => column !== 'selection'); + }); + }, [setHiddenColumns]); + const handleMultipleSelectedRows = (selectedRowIds, rows, currentRow, currentRowIndex) => { + const keys = Object.keys(selectedRowIds); + if (onMultiSelectionChanged) { + if (currentRow.isSelected) { + // we remove the item from the list + onMultiSelectionChanged(rows.filter((row) => keys.includes(row.id) && rows[currentRowIndex].id !== row.id)); + } + else { + // we add the new item from the list + onMultiSelectionChanged([ + ...rows.filter((row) => keys.includes(row.id)), + rows[currentRowIndex], + ]); + } + } + currentRow.toggleRowSelected(!currentRow.isSelected); + }; + const { hasScrollbar, scrollBarWidth, handleScrollbarWidth } = useTableScrollbar(); + const { headerRef } = useSyncedScroll(); + const RenderRow = memo(({ index, style }) => { + const row = rows[index]; + prepareRow(row); + const rowProps = { + ...row.getRowProps({ + /** + * Note:We need to pass the style property to the row component. + * Otherwise when we scroll down, the next rows are flashing + * because they are re-rendered in loop. + */ + style: { ...style }, + }), + onClick: onSingleRowSelected + ? () => { + onSingleRowSelected(row); + toggleAllRowsSelected(false); + row.toggleRowSelected(true); + } + : () => handleMultipleSelectedRows(selectedRowIds, rows, row, index), + }; + return (_jsx(TableRowMultiSelectable, { ...rowProps, isSelected: row.isSelected, separationLineVariant: separationLineVariant, className: "tr", children: row.cells.map((cell) => { + const cellProps = cell.getCellProps({ + style: { + ...cell.column.cellStyle, + // Vertically center the text in cells. + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + }, + role: 'gridcell', + }); + if (cell.column.id === 'selection') { + return (_jsx("div", { ...cellProps, onClick: onSingleRowSelected + ? (event) => { + event.stopPropagation(); + handleMultipleSelectedRows(selectedRowIds, rows, row, index); + } + : undefined, children: cell.render('Cell') })); + } + return (_jsx("div", { ...cellProps, className: "td", children: cell.render('Cell') })); + }) })); + }, areEqual); + return (_jsxs(_Fragment, { children: [_jsx("div", { children: headerGroups.map((headerGroup) => (_jsx(HeadRow, { ...headerGroup.getHeaderGroupProps(), hasScrollBar: hasScrollbar, scrollBarWidth: scrollBarWidth, rowHeight: rowHeight, separationLineVariant: separationLineVariant, ref: headerRef, children: headerGroup.headers.map((column) => { + const headerStyleProps = column.getHeaderProps(Object.assign(column.getSortByToggleProps(), { + style: { ...column === null || column === void 0 ? void 0 : column.cellStyle, position: 'relative' }, + })); + return (_jsx(TableHeader, { ...headerStyleProps, role: "columnheader", tabIndex: !column.disableSortBy ? 0 : undefined, onKeyDown: (event) => { + if (!column.disableSortBy && + (event.key === ' ' || + event.key === 'Enter' || + event.key === 'Spacebar')) { + event.preventDefault(); + // @ts-expect-error - getSortByToggleProps is joined to getHeaderProps + headerStyleProps.onClick(event); + } + }, children: _jsxs("div", { children: [column.id === 'selection' ? (_jsx("div", { onClick: (event) => { + const eventTarget = event.target; + if (onToggleAll) { + onToggleAll(eventTarget.checked); + } + if (onMultiSelectionChanged) { + if (isAllRowsSelected) { + onMultiSelectionChanged([]); + } + else { + onMultiSelectionChanged(rows); + } + } + }, children: column.render('Header') })) : (column.render('Header')), _jsx(SortCaret, { column: column })] }) })); + }) }))) }), _jsx(TableBody, { role: "rowgroup", className: "tbody", ref: handleScrollbarWidth, children: _jsx(TableRows, { locale: locale, children: children, customItemKey: customItemKey, RenderRow: RenderRow }) }), isLoadingMoreItems && (_jsx(Box, { display: "flex", justifyContent: "center", marginTop: spacing.r16, marginBottom: spacing.r16, children: _jsx(Loader, { size: "large" }) }))] })); +}; diff --git a/dist/components/tablev2/Search.d.ts b/dist/components/tablev2/Search.d.ts new file mode 100644 index 0000000000..d55eb0d5f2 --- /dev/null +++ b/dist/components/tablev2/Search.d.ts @@ -0,0 +1,22 @@ +import { Props } from '../searchinput/SearchInput.component'; +import { TableLocalType } from './TableUtils'; +export type DisplayedName = { + plural: string; + singular: string; +}; +export type SearchProps = { + onChange: (arg0: string) => void; + value?: string; + locale?: TableLocalType; + totalCount?: number; +} & Omit; +export declare const TableItemCount: ({ entity, count, locale, }: { + entity: { + singular: string; + plural: string; + }; + count: number; + locale: "en" | "fr"; +}) => import("react/jsx-runtime").JSX.Element; +export declare function TableSearch(props: SearchProps): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=Search.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/Search.d.ts.map b/dist/components/tablev2/Search.d.ts.map new file mode 100644 index 0000000000..16e701abcc --- /dev/null +++ b/dist/components/tablev2/Search.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Search.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/Search.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AA0B5B,eAAO,MAAM,cAAc,+BAIxB;IACD,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;CACrB,4CAYA,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,2CAiC7C"} \ No newline at end of file diff --git a/dist/components/tablev2/Search.js b/dist/components/tablev2/Search.js new file mode 100644 index 0000000000..2792d85bed --- /dev/null +++ b/dist/components/tablev2/Search.js @@ -0,0 +1,48 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import React from 'react'; +import styled from 'styled-components'; +import { useTableContext } from './Tablev2.component'; +import { SearchInput } from '../searchinput/SearchInput.component'; +import { BasicText } from '../text/Text.component'; +import { spacing } from '../../spacing'; +const SearchContainer = styled.div ` + display: flex; + align-items: center; +`; +const ResultContainer = styled(BasicText) ` + font-weight: bold; +`; +const translations = { + en: { + search: 'Search', + total: 'Total: ', + }, + fr: { + search: `Rechercher`, + total: `Total : `, + }, +}; +const TableItemCountContainer = styled(BasicText) ` + display: flex; + flex-direction: column; + margin-right: ${spacing.r8}; + min-width: 4.3rem; +`; +export const TableItemCount = ({ entity, count, locale, }) => { + return (_jsxs(TableItemCountContainer, { children: [_jsx("span", { children: translations[locale].total }), _jsxs(ResultContainer, { children: [count, ' ', count > 1 + ? entity.plural + : (count === 1 || count === 0) && entity.singular] })] })); +}; +export function TableSearch(props) { + const { onChange, value = '', locale = 'en', totalCount, ...rest } = props; + const { setGlobalFilter, rows, preGlobalFilteredRows, entityName = { en: { singular: 'result', plural: 'results' } }, } = useTableContext(); + const totalDispayedRows = totalCount ? totalCount : rows.length; + React.useEffect(() => { + setGlobalFilter(value); + }, [value, setGlobalFilter, preGlobalFilteredRows]); + return (_jsxs(SearchContainer, { children: [_jsx(TableItemCount, { entity: entityName[locale] || entityName.en, count: totalDispayedRows, locale: locale }), _jsx(SearchInput, { value: value, placeholder: translations[locale].search, size: "1", onChange: (evt) => { + if (typeof onChange === 'function') { + onChange(evt.target.value); + } + }, ...rest })] })); +} diff --git a/dist/components/tablev2/SearchWithQueryParams.d.ts b/dist/components/tablev2/SearchWithQueryParams.d.ts new file mode 100644 index 0000000000..56c33d85dd --- /dev/null +++ b/dist/components/tablev2/SearchWithQueryParams.d.ts @@ -0,0 +1,6 @@ +import { SearchProps } from './Search'; +export type SearchWithQueryParamsProps = { + queryParams?: string; +} & Omit & Partial>; +export declare function SearchWithQueryParams(props: SearchWithQueryParamsProps): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=SearchWithQueryParams.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/SearchWithQueryParams.d.ts.map b/dist/components/tablev2/SearchWithQueryParams.d.ts.map new file mode 100644 index 0000000000..850dbf4301 --- /dev/null +++ b/dist/components/tablev2/SearchWithQueryParams.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SearchWithQueryParams.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/SearchWithQueryParams.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAyB,WAAW,EAAE,MAAM,UAAU,CAAC;AAE9D,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,CAAC,GACzC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;AAEzC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,2CA6BtE"} \ No newline at end of file diff --git a/dist/components/tablev2/SearchWithQueryParams.js b/dist/components/tablev2/SearchWithQueryParams.js new file mode 100644 index 0000000000..d1cde70682 --- /dev/null +++ b/dist/components/tablev2/SearchWithQueryParams.js @@ -0,0 +1,24 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { useState } from 'react'; +import { useLocation, useHistory } from 'react-router-dom'; +import { TableSearch as Search } from './Search'; +export function SearchWithQueryParams(props) { + const { queryParams = 'search', onChange, ...rest } = props; + const { search, pathname } = useLocation(); + const history = useHistory(); + const params = new URLSearchParams(search); + const initialValue = params.get(queryParams) || ''; + const [value, setValue] = useState(initialValue); + function handleOnChange(value) { + const { onChange } = props; + params.set(queryParams, value); + history.replace(`${pathname}?${params.toString()}`); + setValue(value); + if (typeof onChange === 'function') { + onChange(value); + } + } + return (_jsx(Search, { onChange: handleOnChange, value: value, onReset: () => { + handleOnChange(''); + }, ...rest })); +} diff --git a/dist/components/tablev2/SingleSelectableContent.d.ts b/dist/components/tablev2/SingleSelectableContent.d.ts new file mode 100644 index 0000000000..43921d8901 --- /dev/null +++ b/dist/components/tablev2/SingleSelectableContent.d.ts @@ -0,0 +1,16 @@ +import React from 'react'; +import { Row } from 'react-table'; +import { TableHeightKeyType, TableLocalType, TableVariantType } from './TableUtils'; +export type SingleSelectableContentProps = Record> = { + rowHeight: TableHeightKeyType; + separationLineVariant: TableVariantType; + onRowSelected?: (row: Row) => void; + selectedId?: string; + locale?: TableLocalType; + customItemKey?: (index: number, data: DATA_ROW) => string; + hasScrollbar?: boolean; + isLoadingMoreItems?: boolean; + children?: (rows: React.JSX.Element) => React.JSX.Element; +}; +export declare function SingleSelectableContent = Record>({ rowHeight, separationLineVariant, locale, selectedId, isLoadingMoreItems, onRowSelected, customItemKey, children, }: SingleSelectableContentProps): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=SingleSelectableContent.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/SingleSelectableContent.d.ts.map b/dist/components/tablev2/SingleSelectableContent.d.ts.map new file mode 100644 index 0000000000..ab57aeba53 --- /dev/null +++ b/dist/components/tablev2/SingleSelectableContent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SingleSelectableContent.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/SingleSelectableContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0B,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AASlC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAOtB,MAAM,MAAM,4BAA4B,CACtC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,SAAS,EAAE,kBAAkB,CAAC;IAC9B,qBAAqB,EAAE,gBAAgB,CAAC;IAExC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;CAC3D,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,EACA,SAAiB,EACjB,qBAA0C,EAE1C,MAAa,EACb,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,QAAQ,GACT,EAAE,4BAA4B,CAAC,QAAQ,CAAC,2CAmJxC"} \ No newline at end of file diff --git a/dist/components/tablev2/SingleSelectableContent.js b/dist/components/tablev2/SingleSelectableContent.js new file mode 100644 index 0000000000..f3b7890e04 --- /dev/null +++ b/dist/components/tablev2/SingleSelectableContent.js @@ -0,0 +1,80 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { memo, useEffect } from 'react'; +import { areEqual } from 'react-window'; +import { useTableContext } from './Tablev2.component'; +import { HeadRow, TableRow, TableBody, TableHeader, SortCaret, } from './Tablestyle'; +import { TableRows, useTableScrollbar } from './TableCommon'; +import useSyncedScroll from './useSyncedScroll'; +import { Loader } from '../loader/Loader.component'; +import { Box } from '../box/Box'; +import { spacing } from '../../spacing'; +export function SingleSelectableContent({ rowHeight = 'h40', separationLineVariant = 'backgroundLevel3', locale = 'en', selectedId, isLoadingMoreItems, onRowSelected, customItemKey, children, }) { + if (selectedId && !onRowSelected) { + console.error('Please specify the onRowSelected function.'); + } + const { headerRef } = useSyncedScroll(); + const { headerGroups, prepareRow, rows, setRowHeight } = useTableContext(); + useEffect(() => { + setRowHeight(rowHeight); + }, [rowHeight, setRowHeight]); + const RenderRow = memo(({ index, style }) => { + const row = rows[index]; + prepareRow(row); + let rowProps = row.getRowProps({ + /** + * Note: We need to pass the style property to the row component. + * Otherwise when we scroll down, the next rows are flashing + * because they are re-rendered in loop. + */ + style: { ...style }, + }); + rowProps = { + ...rowProps, + ...{ + onClick: () => { + if (onRowSelected) + return onRowSelected(row); + }, + tabIndex: onRowSelected ? 0 : undefined, + onKeyDown: (event) => { + if (onRowSelected && + (event.key === ' ' || + event.key === 'Enter' || + event.key === 'Spacebar')) { + event.preventDefault(); + onRowSelected(row); + } + }, + }, + }; + return (_jsx(TableRow, { ...rowProps, isSelected: selectedId === row.id, "aria-selected": selectedId === row.id ? 'true' : 'false', separationLineVariant: separationLineVariant, selectedId: selectedId, className: "tr", children: row.cells.map((cell) => { + let cellProps = cell.getCellProps({ + style: { + ...cell.column.cellStyle, + // Vertically center the text in cells. + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + }, + role: 'gridcell', + }); + return (_jsx("div", { ...cellProps, className: "td", children: cell.render('Cell') })); + }) })); + }, areEqual); + const { hasScrollbar, scrollBarWidth, handleScrollbarWidth } = useTableScrollbar(); + return (_jsxs(_Fragment, { children: [_jsx("div", { className: "thead", role: "rowgroup", children: headerGroups.map((headerGroup) => (_jsx(HeadRow, { ...headerGroup.getHeaderGroupProps(), ref: headerRef, separationLineVariant: separationLineVariant, hasScrollBar: hasScrollbar, scrollBarWidth: scrollBarWidth, rowHeight: rowHeight, style: { overflow: 'hidden' }, children: headerGroup.headers.map((column) => { + const headerStyleProps = column.getHeaderProps(Object.assign(column.getSortByToggleProps(), { + style: { ...column.cellStyle, position: 'relative' }, + })); + return (_jsx(TableHeader, { ...headerStyleProps, role: "columnheader", tabIndex: !column.disableSortBy ? 0 : undefined, onKeyDown: (event) => { + if (!column.disableSortBy && + (event.key === ' ' || + event.key === 'Enter' || + event.key === 'Spacebar')) { + event.preventDefault(); + // @ts-expect-error - getSortByToggleProps is joined to getHeaderProps + headerStyleProps.onClick(event); + } + }, children: _jsxs("div", { children: [column.render('Header'), _jsx(SortCaret, { column: column })] }) })); + }) }))) }), _jsx(TableBody, { role: "rowgroup", className: "tbody", ref: handleScrollbarWidth, children: _jsx(TableRows, { locale: locale, children: children, customItemKey: customItemKey, RenderRow: RenderRow }) }), isLoadingMoreItems && (_jsx(Box, { display: "flex", justifyContent: "center", marginTop: spacing.r16, marginBottom: spacing.r16, children: _jsx(Loader, { size: "large" }) }))] })); +} diff --git a/dist/components/tablev2/TableCommon.d.ts b/dist/components/tablev2/TableCommon.d.ts new file mode 100644 index 0000000000..427828915a --- /dev/null +++ b/dist/components/tablev2/TableCommon.d.ts @@ -0,0 +1,36 @@ +import React, { ComponentType, LegacyRef } from 'react'; +import { Row } from 'react-table'; +import { FixedSizeList, ListChildComponentProps, ListItemKeySelector } from 'react-window'; +import { TableHeightKeyType, TableLocalType } from './TableUtils'; +import { CSSProperties } from 'styled-components'; +type VirtualizedRowsType = Record> = { + rows: Row[]; + RenderRow: ComponentType[]>>>; + rowHeight: TableHeightKeyType; + setHasScrollbar: React.Dispatch>; + hasScrollbar?: boolean; + itemKey?: ListItemKeySelector[]>; + onBottom?: (rowLength: number) => void; + onBottomOffset?: number; + listRef?: LegacyRef[]>>; +}; +export declare const VirtualizedRows: = Record>({ rows, rowHeight, setHasScrollbar, onBottom, onBottomOffset, RenderRow, listRef, itemKey, }: VirtualizedRowsType) => import("react/jsx-runtime").JSX.Element; +export declare const useTableScrollbar: () => { + hasScrollbar: boolean | undefined; + setHasScrollbar: React.Dispatch>; + scrollBarWidth: number; + handleScrollbarWidth: (node: any) => void; +}; +export type RenderRowType = { + index: number; + style: CSSProperties; +}; +type TableRowsProps = Record> = { + locale?: TableLocalType; + children?: (children: JSX.Element) => JSX.Element; + customItemKey?: (index: number, data: DATA_ROW) => string; + RenderRow: React.MemoExoticComponent<({ index, style }: RenderRowType) => JSX.Element>; +}; +export declare function TableRows = Record>({ locale, children, customItemKey, RenderRow }: TableRowsProps): import("react/jsx-runtime").JSX.Element | null; +export {}; +//# sourceMappingURL=TableCommon.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/TableCommon.d.ts.map b/dist/components/tablev2/TableCommon.d.ts.map new file mode 100644 index 0000000000..31c1eb7409 --- /dev/null +++ b/dist/components/tablev2/TableCommon.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TableCommon.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/TableCommon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,SAAS,EAAyB,MAAM,OAAO,CAAC;AAC/E,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,OAAO,EACL,aAAa,EAEb,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,kBAAkB,EAClB,cAAc,EAEf,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,KAAK,mBAAmB,CACtB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtB,SAAS,EAAE,aAAa,CACtB,KAAK,CAAC,iBAAiB,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAClE,CAAC;IACF,SAAS,EAAE,kBAAkB,CAAC;IAC9B,eAAe,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,0HAUvC,mBAAmB,CAAC,QAAQ,CAAC,4CAmC/B,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;CAwB7B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,KAAK,cAAc,CACjB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC1D,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAClC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,aAAa,KAAK,GAAG,CAAC,OAAO,CACjD,CAAC;CACH,CAAC;AACF,wBAAgB,SAAS,CACvB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,kDAyEzE"} \ No newline at end of file diff --git a/dist/components/tablev2/TableCommon.js b/dist/components/tablev2/TableCommon.js new file mode 100644 index 0000000000..b3e4421fe4 --- /dev/null +++ b/dist/components/tablev2/TableCommon.js @@ -0,0 +1,69 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { useCallback, useState } from 'react'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { FixedSizeList as List, } from 'react-window'; +import { convertRemToPixels, tableRowHeight, } from './TableUtils'; +import { useTableContext } from './Tablev2.component'; +import useSyncedScroll from './useSyncedScroll'; +import { UnsuccessfulResult } from '../UnsuccessfulResult.component'; +export const VirtualizedRows = ({ rows, rowHeight, setHasScrollbar, onBottom, onBottomOffset, RenderRow, listRef, itemKey, }) => (_jsx(AutoSizer, { disableWidth: true, children: ({ height }) => { + return (_jsx(List, { height: height - 1, itemCount: rows.length, itemSize: convertRemToPixels(tableRowHeight[rowHeight]), width: '100%', itemKey: itemKey, itemData: rows, ref: listRef, onItemsRendered: ({ visibleStartIndex, visibleStopIndex, overscanStopIndex, }) => { + setHasScrollbar(visibleStopIndex - visibleStartIndex < overscanStopIndex); + if (onBottom && + onBottomOffset != null && + overscanStopIndex >= rows.length - 1 - onBottomOffset) { + onBottom(rows.length); + } + }, children: RenderRow })); + } })); +export const useTableScrollbar = () => { + const { hasScrollbar, setHasScrollbar } = useTableContext(); + const [scrollBarWidth, setScrollBarWidth] = useState(0); + const handleScrollbarWidth = useCallback((node) => { + if (node) { + const scrollDiv = document.createElement('div'); + scrollDiv.setAttribute('style', 'width: 100px; height: 100px; overflow: scroll; position:absolute; top:-9999px;'); + node.appendChild(scrollDiv); + const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + node.removeChild(scrollDiv); + setScrollBarWidth(scrollbarWidth); + } + }, []); + return { + hasScrollbar, + setHasScrollbar, + scrollBarWidth, + handleScrollbarWidth, + }; +}; +export function TableRows({ locale, children, customItemKey, RenderRow }) { + const { setHasScrollbar } = useTableScrollbar(); + const { rows, status, entityName, rowHeight, onBottom, onBottomOffset } = useTableContext(); + const { bodyRef } = useSyncedScroll(); + function itemKey(index, data) { + if (typeof customItemKey === 'function') { + return customItemKey(index, data); + } + return index; + } + if (status === 'idle' || status === 'loading' || status === 'error') { + return (_jsx(UnsuccessfulResult, { name: entityName, status: status, locale: locale, rowHeight: rowHeight })); + } + if (status === 'success' || status === undefined) { + if (typeof children === 'function') { + if (rows.length) { + return children(_jsx(VirtualizedRows, { rows: rows, listRef: bodyRef, itemKey: itemKey, rowHeight: rowHeight, setHasScrollbar: setHasScrollbar, onBottom: onBottom, onBottomOffset: onBottomOffset, RenderRow: RenderRow })); + } + else { + return children(_jsx(UnsuccessfulResult, { rowHeight: rowHeight, name: entityName, status: "noResult" })); + } + } + else if (rows.length) { + return (_jsx(VirtualizedRows, { rows: rows, listRef: bodyRef, setHasScrollbar: setHasScrollbar, onBottom: onBottom, onBottomOffset: onBottomOffset, itemKey: itemKey, rowHeight: rowHeight, RenderRow: RenderRow })); + } + else { + return (_jsx(UnsuccessfulResult, { rowHeight: rowHeight, name: entityName, status: "noResult" })); + } + } + return null; +} diff --git a/dist/components/tablev2/TableUtils.d.ts b/dist/components/tablev2/TableUtils.d.ts new file mode 100644 index 0000000000..0797ab79d6 --- /dev/null +++ b/dist/components/tablev2/TableUtils.d.ts @@ -0,0 +1,29 @@ +declare const STATUS_CRITICAL = "critical"; +declare const STATUS_WARNING = "warning"; +declare const STATUS_NONE = "none"; +declare const STATUS_HEALTH = "healthy"; +type StatusType = typeof STATUS_CRITICAL | typeof STATUS_WARNING | typeof STATUS_NONE | typeof STATUS_HEALTH; +export declare function compareHealth(status1: StatusType, status2: StatusType): number | undefined; +export declare function convertRemToPixels(rem: any): number; +export type TableLocalType = 'en' | 'fr'; +export type TableHeightKeyType = 'h32' | 'h40' | 'h48' | 'h64'; +export type TableVariantType = 'backgroundLevel1' | 'backgroundLevel2' | 'backgroundLevel3' | 'backgroundLevel4'; +export declare const tableRowHeight: { + h32: string; + h40: string; + h48: string; + h64: string; +}; +type TableMessagesType = 'error' | 'loading' | 'idle' | 'noResult'; +export declare const translatedMessages: (type: TableMessagesType, entityName?: { + en: { + singular: string; + plural: string; + }; + fr?: { + singular: string; + plural: string; + }; +}, locale?: TableLocalType) => string; +export {}; +//# sourceMappingURL=TableUtils.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/TableUtils.d.ts.map b/dist/components/tablev2/TableUtils.d.ts.map new file mode 100644 index 0000000000..609dd52d29 --- /dev/null +++ b/dist/components/tablev2/TableUtils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TableUtils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/TableUtils.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,eAAe,aAAa,CAAC;AACnC,QAAA,MAAM,cAAc,YAAY,CAAC;AACjC,QAAA,MAAM,WAAW,SAAS,CAAC;AAC3B,QAAA,MAAM,aAAa,YAAY,CAAC;AAEhC,KAAK,UAAU,GACX,OAAO,eAAe,GACtB,OAAO,cAAc,GACrB,OAAO,WAAW,GAClB,OAAO,aAAa,CAAC;AAGzB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,UAAU,GAClB,MAAM,GAAG,SAAS,CAuBpB;AAED,wBAAgB,kBAAkB,CAAC,GAAG,KAAA,UAErC;AACD,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAE/D,MAAM,MAAM,gBAAgB,GACxB,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,CAAC;AAGvB,eAAO,MAAM,cAAc;;;;;CAK1B,CAAC;AAEF,KAAK,iBAAiB,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnE,eAAO,MAAM,kBAAkB,SACvB,iBAAiB,eACV;IACX,EAAE,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,EAAE,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,WACQ,cAAc,WA2BxB,CAAC"} \ No newline at end of file diff --git a/dist/components/tablev2/TableUtils.js b/dist/components/tablev2/TableUtils.js new file mode 100644 index 0000000000..e25cce85be --- /dev/null +++ b/dist/components/tablev2/TableUtils.js @@ -0,0 +1,55 @@ +const STATUS_CRITICAL = 'critical'; +const STATUS_WARNING = 'warning'; +const STATUS_NONE = 'none'; +const STATUS_HEALTH = 'healthy'; +// some common customized sortTypes +export function compareHealth(status1, status2) { + if (![STATUS_WARNING, STATUS_CRITICAL, STATUS_NONE, STATUS_HEALTH].includes(status1) || + ![STATUS_WARNING, STATUS_CRITICAL, STATUS_NONE, STATUS_HEALTH].includes(status2)) { + console.error('Invalid health status'); + return; + } + const weights = {}; + weights[STATUS_CRITICAL] = 3; + weights[STATUS_WARNING] = 2; + weights[STATUS_NONE] = 1; + weights[STATUS_HEALTH] = 0; + return weights[status1] === weights[status2] + ? 0 + : weights[status1] > weights[status2] + ? 1 + : -1; +} +export function convertRemToPixels(rem) { + return rem * parseFloat(getComputedStyle(document.documentElement).fontSize); +} +// in rem unit +export const tableRowHeight = { + h32: '2.286', //1 line + h40: '2.858', //2 line + h48: '3.428', //2 line + h64: '4.572', //3 line +}; +export const translatedMessages = (type, entityName, locale) => { + var _a, _b, _c; + if (type === 'error') { + if (locale === 'fr') { + return `Erreur lors du chargement des ${((_a = entityName === null || entityName === void 0 ? void 0 : entityName.fr) === null || _a === void 0 ? void 0 : _a.plural) || 'données'}, veuillez rafraîchir la page.`; + } + return `An error occurred while loading ${entityName ? `the ${entityName.en.plural}` : 'data'}, please refresh the + page.`; + } + if (type === 'loading' || type === 'idle') { + if (locale === 'fr') { + return `Chargement des ${((_b = entityName === null || entityName === void 0 ? void 0 : entityName.fr) === null || _b === void 0 ? void 0 : _b.plural) || 'données'}...`; + } + return `Loading ${(entityName === null || entityName === void 0 ? void 0 : entityName.en.plural) || 'data'}...`; + } + if (type === 'noResult') { + if (locale === 'fr') { + return `Aucun ${((_c = entityName === null || entityName === void 0 ? void 0 : entityName.fr) === null || _c === void 0 ? void 0 : _c.singular) || 'résultat'} trouvé`; + } + return `No ${(entityName === null || entityName === void 0 ? void 0 : entityName.en.plural) || 'results'} found`; + } + return ''; +}; diff --git a/dist/components/tablev2/Tablestyle.d.ts b/dist/components/tablev2/Tablestyle.d.ts new file mode 100644 index 0000000000..d73fac3647 --- /dev/null +++ b/dist/components/tablev2/Tablestyle.d.ts @@ -0,0 +1,34 @@ +import { TableHeightKeyType, TableVariantType } from './TableUtils'; +import { HeaderGroup } from 'react-table'; +export declare const SortIncentive: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>; +export declare const SortCaretWrapper: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>; +export declare const TableHeader: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, { + headerHeight?: number | string; + tabIndex: number | undefined; +}, never>; +type HeadRowType = { + hasScrollBar?: boolean; + scrollBarWidth: number; + rowHeight: TableHeightKeyType; + separationLineVariant: TableVariantType; +}; +export declare const HeadRow: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, HeadRowType, never>; +type TableRowType = { + isSelected: boolean; + selectedId?: string; + separationLineVariant: TableVariantType; +}; +export declare const TableRow: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, TableRowType, never>; +type TableRowMultiSelectableType = { + isSelected: boolean; + separationLineVariant: TableVariantType; +}; +export declare const TableRowMultiSelectable: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, TableRowMultiSelectableType, never>; +export declare const TableBody: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const TableWrapper: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const TooltipContent: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const SortCaret: = Record>({ column, }: { + column: HeaderGroup; +}) => import("react/jsx-runtime").JSX.Element | null; +export {}; +//# sourceMappingURL=Tablestyle.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/Tablestyle.d.ts.map b/dist/components/tablev2/Tablestyle.d.ts.map new file mode 100644 index 0000000000..990fb3c39d --- /dev/null +++ b/dist/components/tablev2/Tablestyle.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Tablestyle.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/Tablestyle.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAElB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,eAAO,MAAM,aAAa,0GAGzB,CAAC;AACF,eAAO,MAAM,gBAAgB,0GAG5B,CAAC;AACF,eAAO,MAAM,WAAW;mBACP,MAAM,GAAG,MAAM;cACpB,MAAM,GAAG,SAAS;SAkB7B,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,qBAAqB,EAAE,gBAAgB,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,OAAO,kHAmBnB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,gBAAgB,CAAC;CACzC,CAAC;AACF,eAAO,MAAM,QAAQ,mHAmCpB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,qBAAqB,EAAE,gBAAgB,CAAC;CACzC,CAAC;AACF,eAAO,MAAM,uBAAuB,kIAqBnC,CAAC;AAEF,eAAO,MAAM,SAAS,yGAKrB,CAAC;AACF,eAAO,MAAM,YAAY,yGAKxB,CAAC;AACF,eAAO,MAAM,cAAc,yGAI1B,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,yCAGvC;IACD,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;CAC/B,mDAgBA,CAAC"} \ No newline at end of file diff --git a/dist/components/tablev2/Tablestyle.js b/dist/components/tablev2/Tablestyle.js new file mode 100644 index 0000000000..3052bde811 --- /dev/null +++ b/dist/components/tablev2/Tablestyle.js @@ -0,0 +1,129 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import styled, { css } from 'styled-components'; +import { tableRowHeight, } from './TableUtils'; +import { Icon } from '../icon/Icon.component'; +import { FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +import { spacing } from '../../spacing'; +const borderSize = '4px'; +export const SortIncentive = styled.span ` + position: absolute; + display: none; +`; +export const SortCaretWrapper = styled.span ` + padding-left: ${spacing.r4}; + position: absolute; +`; +export const TableHeader = styled.div ` + display: flex; + flex-direction: column; + justify-content: center; + height: ${(props) => props.headerHeight}; + cursor: ${(props) => props.tabIndex !== undefined && props.tabIndex >= 0 + ? 'pointer' + : 'default'}; + &:hover { + ${SortIncentive} { + display: block; + } + } + &:focus-visible { + ${FocusVisibleStyle} + } +`; +export const HeadRow = styled.div ` + box-sizing: border-box; + display: flex; + align-items: center; + gap: ${spacing.r16}; + height: 2.286rem; + width: ${(props) => props.hasScrollBar + ? `calc(100% - ${props.scrollBarWidth}px - ${borderSize} )!important` // -4px for border + : `calc(100% - ${borderSize} ) !important`}; + height: ${(props) => tableRowHeight[props.rowHeight]}rem; + table-layout: fixed; + color: ${(props) => props.theme.textPrimary}; + font-weight: bold; + overflow: hidden; + border-bottom: 1px solid + ${(props) => props.theme[props.separationLineVariant]}; + padding-right: ${borderSize}; + padding-left: ${spacing.r16}; +`; +export const TableRow = styled.div ` + color: ${(props) => props.theme.textPrimary}; + gap: ${spacing.r16}; + border-bottom: 1px solid + ${(props) => props.theme[props.separationLineVariant]}; + cursor: default; + box-sizing: border-box; + padding-left: ${spacing.r16}; + padding-right: ${borderSize}; + + // single selectable case + ${(props) => { + if (props.selectedId) { + return css ` + &:hover, + &:focus { + background-color: ${(props) => props.theme.highlight}; + outline: none; + cursor: pointer; + } + &:focus-visible { + ${FocusVisibleStyle} + } + `; + } +}} + + ${(props) => { + if (props.selectedId && props.isSelected) { + return css ` + background-color: ${props.theme.highlight}; + border-right: ${borderSize} solid ${props.theme.selectedActive}; + `; + } +}} +`; +export const TableRowMultiSelectable = styled.div ` + color: ${(props) => props.theme.textPrimary}; + border-bottom: 1px solid + ${(props) => props.theme[props.separationLineVariant]}; + box-sizing: border-box; + ${(props) => { + if (props.isSelected) { + return css ` + background-color: ${(props) => props.theme.highlight}; + border-right: ${borderSize} solid ${props.theme.selectedActive}; + `; + } +}} + padding-right: ${borderSize}; + padding-left: ${spacing.r16}; + &:hover, + &:focus { + background-color: ${(props) => props.theme.highlight}; + outline: none; + cursor: pointer; + } +`; +export const TableBody = styled.div ` + box-sizing: border-box; + display: block; + flex-grow: 1; + height: 100%; +`; +export const TableWrapper = styled.div ` + display: flex; + flex-direction: column; + height: 100%; + width: 100%; +`; +export const TooltipContent = styled.div ` + color: ${(props) => props.theme.textSecondary}; + font-weight: bold; + min-width: 60px; +`; +export const SortCaret = ({ column, }) => { + return !column.disableSortBy ? (_jsx(SortCaretWrapper, { children: column.isSorted ? (column.isSortedDesc ? (_jsx(Icon, { name: "Sort-down" })) : (_jsx(Icon, { name: "Sort-up" }))) : (_jsx(SortIncentive, { children: _jsx(Icon, { name: "Sort" }) })) })) : null; +}; diff --git a/dist/components/tablev2/Tablev2.component.d.ts b/dist/components/tablev2/Tablev2.component.d.ts new file mode 100644 index 0000000000..856fa26084 --- /dev/null +++ b/dist/components/tablev2/Tablev2.component.d.ts @@ -0,0 +1,95 @@ +import * as React from 'react'; +import { CellProps as TableCellProps, CoreUIColumn, HeaderGroup, Row, SortByFn, TableBodyPropGetter, TableBodyProps } from 'react-table'; +import { TableHeightKeyType } from './TableUtils'; +type UpdateTableData = Record> = { + updateTableData?: (rowId: string, columnName: DATA_ROW_KEY, value: DATA_ROW[DATA_ROW_KEY]) => void; +}; +export type Column> = CoreUIColumn; +export type CellProps, V = unknown> = TableCellProps & UpdateTableData; +export type TableProps = Record> = { + columns: Array>; + defaultSortingKey?: string; + data: DATA_ROW[]; + children: JSX.Element | JSX.Element[]; + getRowId?: (originalRow: DATA_ROW, relativeIndex: number, parent?: Row) => string; + sortTypes?: Record>; + globalFilter?: string; + onBottom?: (rowLength: number) => void; + onBottomOffset?: number; + allFilters?: { + id: string; + value: string; + }[]; + status?: 'idle' | 'loading' | 'error' | 'success'; + entityName?: { + en: { + singular: string; + plural: string; + }; + fr?: { + singular: string; + plural: string; + }; + }; + initiallySelectedRowsIds?: Set; +} & UpdateTableData; +type setHiddenColumnFuncType = (oldHidden: string[]) => string[]; +type TableContextType = Record> = { + headerGroups: HeaderGroup[]; + rows: Row[]; + prepareRow: (row: Row) => void; + getTableBodyProps: (propGetter?: TableBodyPropGetter) => TableBodyProps; + rowHeight: TableHeightKeyType; + setRowHeight: (rowHeight: TableHeightKeyType) => void; + selectedRowIds: Record; + selectedFlatRows: Row[]; + preGlobalFilteredRows: Row[]; + setGlobalFilter: (filterValue: string) => void; + globalFilter: any; + setFilter: (columnId: string, updater: any) => void; + onBottom?: (rowLength: number) => void; + onBottomOffset?: number; + setHiddenColumns: (param: string[] | setHiddenColumnFuncType) => void; + isAllRowsSelected?: boolean; + toggleAllRowsSelected: (value?: boolean) => void; + status?: 'idle' | 'loading' | 'error' | 'success'; + entityName?: { + en: { + singular: string; + plural: string; + }; + fr?: { + singular: string; + plural: string; + }; + }; + syncScrollListener: ((event: Event) => void) | null; + setSyncScrollListener: (listener: (event: Event) => void) => void; + setHasScrollbar: React.Dispatch>; + hasScrollbar?: boolean; +}; +export declare const useTableContext: = Record>() => TableContextType; +export declare const EmptyCell: ({ tooltipContent, mr, }: { + tooltipContent?: string | JSX.Element; + mr?: number; +}) => import("react/jsx-runtime").JSX.Element; +declare function Table = Record>({ columns, data, defaultSortingKey, getRowId, children, sortTypes, globalFilter, allFilters, onBottom, onBottomOffset, initiallySelectedRowsIds, updateTableData, status, entityName, }: TableProps): import("react/jsx-runtime").JSX.Element; +declare namespace Table { + var SingleSelectableContent: typeof import("./SingleSelectableContent").SingleSelectableContent; + var MultiSelectableContent: = Record>({ onMultiSelectionChanged, onSingleRowSelected, onToggleAll, rowHeight, separationLineVariant, locale, customItemKey, isLoadingMoreItems, children, }: { + onMultiSelectionChanged?: ((rows: Row[]) => void) | undefined; + onSingleRowSelected?: ((row: Row) => void) | undefined; + onToggleAll?: (selected: boolean) => void; + rowHeight?: TableHeightKeyType; + separationLineVariant?: import("./TableUtils").TableVariantType; + locale?: import("./TableUtils").TableLocalType; + customItemKey?: ((index: number, data: DATA_ROW) => string) | undefined; + hasScrollbar?: boolean; + isLoadingMoreItems?: boolean; + children?: (rows: JSX.Element) => JSX.Element; + }) => import("react/jsx-runtime").JSX.Element; + var Search: typeof import("./Search").TableSearch; + var SearchWithQueryParams: typeof import("./SearchWithQueryParams").SearchWithQueryParams; +} +export { Table }; +//# sourceMappingURL=Tablev2.component.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/Tablev2.component.d.ts.map b/dist/components/tablev2/Tablev2.component.d.ts.map new file mode 100644 index 0000000000..5f6c0fd7c7 --- /dev/null +++ b/dist/components/tablev2/Tablev2.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Tablev2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/Tablev2.component.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAEL,SAAS,IAAI,cAAc,EAC3B,YAAY,EACZ,WAAW,EAEX,GAAG,EACH,QAAQ,EACR,mBAAmB,EACnB,cAAc,EASf,MAAM,aAAa,CAAC;AAWrB,OAAO,EAAiB,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIjE,KAAK,eAAe,CAClB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,eAAe,CAAC,EAAE,CAAC,YAAY,SAAS,MAAM,QAAQ,EACpD,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,YAAY,EACxB,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,KAC1B,IAAI,CAAC;CACX,CAAC;AACF,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;AACxE,MAAM,MAAM,SAAS,CACnB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,GAAG,OAAO,IACT,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;AAE9C,MAAM,MAAM,UAAU,CACpB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,QAAQ,EAAE,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,CACT,WAAW,EAAE,QAAQ,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,KACnB,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAClD,UAAU,CAAC,EAAE;QACX,EAAE,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QACzC,EAAE,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;IACF,wBAAwB,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;CAEjD,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;AAE9B,KAAK,uBAAuB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;AAEjE,KAAK,gBAAgB,CACnB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAChE;IACF,YAAY,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtB,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IACzC,iBAAiB,EAAE,CACjB,UAAU,CAAC,EAAE,mBAAmB,CAAC,QAAQ,CAAC,KACvC,cAAc,CAAC;IACpB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,YAAY,EAAE,CAAC,SAAS,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,gBAAgB,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;IAClC,qBAAqB,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;IACvC,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,YAAY,EAAE,GAAG,CAAC;IAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,uBAAuB,KAAK,IAAI,CAAC;IACtE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAClD,UAAU,CAAC,EAAE;QACX,EAAE,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QACzC,EAAE,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;IACF,kBAAkB,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACpD,qBAAqB,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;IAClE,eAAe,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAGF,eAAO,MAAM,eAAe,GAC1B,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,iCAUnB,gBAAgB,CAAC,QAAQ,CAC/C,CAAC;AAEF,eAAO,MAAM,SAAS,4BAGnB;IACD,cAAc,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,4CAUA,CAAC;AAyBF,iBAAS,KAAK,CACZ,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,EACA,OAAO,EACP,IAAI,EACJ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,cAAmB,EACnB,wBAAwB,EACxB,eAAe,EACf,MAAM,EACN,UAAU,GACX,EAAE,UAAU,CAAC,QAAQ,CAAC,2CAuJtB;kBAxKQ,KAAK;;;;;;;;;;;;0BApIS,IAAK,OAAO,KAAI,IAAM,OAAM;;;;;AAkTnD,OAAO,EAAE,KAAK,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/tablev2/Tablev2.component.js b/dist/components/tablev2/Tablev2.component.js new file mode 100644 index 0000000000..7bbd6b926a --- /dev/null +++ b/dist/components/tablev2/Tablev2.component.js @@ -0,0 +1,152 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +/// +import * as React from 'react'; +import { useEffect } from 'react'; +import { useBlockLayout, useExpanded, useFilters, useGlobalFilter, useRowSelect, useSortBy, useTable, defaultColumn, } from 'react-table'; +import { useMemoCompare } from '../../hooks'; +import { Box } from '../box/Box'; +import { ConstrainedText } from '../constrainedtext/Constrainedtext.component'; +import { Tooltip } from '../tooltip/Tooltip.component'; +import { MultiSelectableContent } from './MultiSelectableContent'; +import { TableSearch as Search } from './Search'; +import { SearchWithQueryParams } from './SearchWithQueryParams'; +import { SingleSelectableContent } from './SingleSelectableContent'; +import { TableWrapper, TooltipContent } from './Tablestyle'; +import { compareHealth } from './TableUtils'; +import { useCheckbox } from './useCheckbox'; +import { Icon } from '../icon/Icon.component'; +const TableContext = React.createContext(null); +export const useTableContext = () => { + const tableProps = React.useContext(TableContext); + if (!tableProps) { + throw new Error('The useTableContext hook can only be used within the '); + } + return tableProps; //Todo figure out a way to transfer the type to the context provider +}; +export const EmptyCell = ({ tooltipContent, mr = 4, }) => { + return (_jsx(Box, { mr: mr, children: _jsx(Tooltip, { overlay: _jsx(TooltipContent, { children: tooltipContent || 'unknown' }), children: _jsx(Icon, { name: "Minus" }) }) })); +}; +const DefaultRenderer = ({ value }) => { + const { rowHeight } = useTableContext(); + if (!value && value !== 0) { + return _jsx(EmptyCell, {}); + } + if (typeof value === 'string') { + const lineClamp = rowHeight === 'h32' + ? 1 + : rowHeight === 'h40' || rowHeight === 'h48' + ? 2 + : 3; + return (_jsx(Box, { mr: 4, children: _jsx(ConstrainedText, { text: value, lineClamp: lineClamp }) })); + } + return value; +}; +function Table({ columns, data, defaultSortingKey, getRowId, children, sortTypes, globalFilter, allFilters, onBottom, onBottomOffset = 10, initiallySelectedRowsIds, updateTableData, status, entityName, }) { + sortTypes = { + health: (row1, row2) => { + return compareHealth(row2.values.health, row1.values.health) || 0; + }, + ...sortTypes, + }; + const stringifyFilter = React.useMemo(() => { + return (rows, columnIds, value) => { + const filteredRows = rows.filter((row) => { + // we stringify the object to make sure we can match the value + return JSON.stringify(row.values) + .toLowerCase() + .includes((value || '').toLowerCase()); + }); + return filteredRows; + }; + }, []); + const formattedInitiallySelectedRows = React.useMemo(() => { + if (initiallySelectedRowsIds) { + return Array.from(initiallySelectedRowsIds).reduce((accumulatedValue, currentValue) => ({ + ...accumulatedValue, + [currentValue]: true, + }), {}); + } + return {}; + }, []); + const [rowHeight, setRowHeight] = React.useState('h40'); + const [syncScrollListener, setSyncScrollListener] = React.useState(null); + const [hasScrollbar, setHasScrollbar] = React.useState(false); + const { headerGroups, rows, prepareRow, selectedFlatRows, getTableBodyProps, state: { selectedRowIds }, preGlobalFilteredRows, setGlobalFilter, setFilter, setAllFilters, setHiddenColumns, isAllRowsSelected, toggleAllRowsSelected, } = useTable({ + defaultColumn: { + ...defaultColumn, + Cell: DefaultRenderer, + }, + columns: columns, + data, + getRowId, + initialState: { + sortBy: defaultSortingKey + ? [ + { + id: defaultSortingKey, + desc: false, + }, + ] + : [], + selectedRowIds: formattedInitiallySelectedRows, + hiddenColumns: ['selection'], + }, + disableMultiSort: true, + autoResetSortBy: false, + sortTypes, + //@ts-ignore TODO investigate why this type is not matching + globalFilter: stringifyFilter, + autoResetHiddenColumns: false, + updateTableData, + }, useBlockLayout, useFilters, useGlobalFilter, useSortBy, useExpanded, useRowSelect, useCheckbox); + useEffect(() => { + if (globalFilter !== undefined && globalFilter !== null) { + setGlobalFilter(globalFilter); + } + }, [globalFilter, setGlobalFilter, data]); + const filters = useMemoCompare(allFilters, (previous, next) => !previous || JSON.stringify(previous) === JSON.stringify(next)); + useEffect(() => { + if (!filters) { + setAllFilters([]); + } + else { + const validFilters = filters.filter((filter) => filter.id && filter.value !== undefined); + setAllFilters(validFilters.length > 0 ? validFilters : []); + } + }, [filters, setAllFilters]); + const contextValue = { + headerGroups, + rows, + prepareRow, + getTableBodyProps, + selectedRowIds, + selectedFlatRows, + preGlobalFilteredRows, + setGlobalFilter, + rowHeight, + setRowHeight, + globalFilter, + setFilter, + onBottom, + onBottomOffset, + setHiddenColumns, + isAllRowsSelected, + toggleAllRowsSelected, + status, + entityName, + syncScrollListener, + setSyncScrollListener, + setHasScrollbar, + hasScrollbar, + }; + return (_jsx(TableContext.Provider + //@ts-ignore + , { + //@ts-ignore + value: contextValue, children: _jsx(TableWrapper, { role: "grid", className: "table", children: children }) })); +} +Table.SingleSelectableContent = SingleSelectableContent; +Table.MultiSelectableContent = MultiSelectableContent; +Table.Search = Search; +Table.SearchWithQueryParams = SearchWithQueryParams; +export { Table }; diff --git a/dist/components/tablev2/react-table-config.d.ts b/dist/components/tablev2/react-table-config.d.ts new file mode 100644 index 0000000000..65d92ee424 --- /dev/null +++ b/dist/components/tablev2/react-table-config.d.ts @@ -0,0 +1,28 @@ +import { CSSProperties } from 'react'; +declare module 'react-table' { + interface Hooks extends UseExpandedHooks, UseGroupByHooks, UseRowSelectHooks, UseTableHooks, UseSortByHooks { + } + interface TableInstance extends UseColumnOrderInstanceProps, UseExpandedInstanceProps, UseFiltersInstanceProps, UseGlobalFiltersInstanceProps, UseGroupByInstanceProps, UsePaginationInstanceProps, UseRowSelectInstanceProps, UseRowStateInstanceProps, UseSortByInstanceProps { + } + function useTable(options: TableOptions, ...plugins: Array>): TableInstance; + interface TableState extends UseColumnOrderState, UseExpandedState, UseFiltersState, UseGlobalFiltersState, UseGroupByState, UsePaginationState, UseResizeColumnsState, UseRowSelectState, UseRowStateState, UseSortByState { + } + interface Cell extends UseGroupByCellProps, UseRowStateCellProps { + } + interface Row extends UseExpandedRowProps, UseGroupByRowProps, UseRowSelectRowProps, UseRowStateRowProps { + } + interface ColumnInterface extends UseFiltersColumnOptions, UseGlobalFiltersColumnOptions, UseGroupByColumnOptions, UseResizeColumnsColumnOptions, UseSortByColumnOptions, UseTableColumnOptions { + } + type CoreUIColumn = Column & { + cellStyle?: CSSProperties; + }; + interface ColumnInstance extends UseFiltersColumnProps, UseGroupByColumnProps, UseResizeColumnsColumnProps, UseSortByColumnProps { + cellStyle?: CSSProperties; + } + interface CoreUIUseTableOptions extends UseTableOptions { + columns: ReadonlyArray>; + } + interface TableOptions extends UseExpandedOptions, UseFiltersOptions, UseGlobalFiltersOptions, UseGroupByOptions, UsePaginationOptions, UseResizeColumnsOptions, UseRowSelectOptions, UseRowStateOptions, UseSortByOptions, CoreUIUseTableOptions, Record { + } +} +//# sourceMappingURL=react-table-config.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/react-table-config.d.ts.map b/dist/components/tablev2/react-table-config.d.ts.map new file mode 100644 index 0000000000..22f2d38de0 --- /dev/null +++ b/dist/components/tablev2/react-table-config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"react-table-config.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/react-table-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAiB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,CAC1C,SAAQ,gBAAgB,CAAC,CAAC,CAAC,EACzB,eAAe,CAAC,CAAC,CAAC,EAClB,iBAAiB,CAAC,CAAC,CAAC,EACpB,aAAa,CAAC,CAAC,CAAC,EAChB,cAAc,CAAC,CAAC,CAAC;KAAG;IAExB,UAAiB,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,CAClD,SAAQ,2BAA2B,CAAC,CAAC,CAAC,EACpC,wBAAwB,CAAC,CAAC,CAAC,EAC3B,uBAAuB,CAAC,CAAC,CAAC,EAC1B,6BAA6B,CAAC,CAAC,CAAC,EAChC,uBAAuB,CAAC,CAAC,CAAC,EAC1B,0BAA0B,CAAC,CAAC,CAAC,EAC7B,yBAAyB,CAAC,CAAC,CAAC,EAC5B,wBAAwB,CAAC,CAAC,CAAC,EAC3B,sBAAsB,CAAC,CAAC,CAAC;KAAG;IAEhC,SAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,EAC5C,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EACxB,GAAG,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAC/B,aAAa,CAAC,CAAC,CAAC,CAAC;IAEpB,UAAiB,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,CAC/C,SAAQ,mBAAmB,CAAC,CAAC,CAAC,EAC5B,gBAAgB,CAAC,CAAC,CAAC,EACnB,eAAe,CAAC,CAAC,CAAC,EAClB,qBAAqB,CAAC,CAAC,CAAC,EACxB,eAAe,CAAC,CAAC,CAAC,EAClB,kBAAkB,CAAC,CAAC,CAAC,EACrB,qBAAqB,CAAC,CAAC,CAAC,EACxB,iBAAiB,CAAC,CAAC,CAAC,EACpB,gBAAgB,CAAC,CAAC,CAAC,EACnB,cAAc,CAAC,CAAC,CAAC;KAAG;IAExB,UAAiB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAClD,SAAQ,mBAAmB,CAAC,CAAC,CAAC,EAC5B,oBAAoB,CAAC,CAAC,CAAC;KAAG;IAE9B,UAAiB,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,CACxC,SAAQ,mBAAmB,CAAC,CAAC,CAAC,EAC5B,kBAAkB,CAAC,CAAC,CAAC,EACrB,oBAAoB,CAAC,CAAC,CAAC,EACvB,mBAAmB,CAAC,CAAC,CAAC;KAAG;IAE7B,UAAiB,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,CACpD,SAAQ,uBAAuB,CAAC,CAAC,CAAC,EAChC,6BAA6B,CAAC,CAAC,CAAC,EAChC,uBAAuB,CAAC,CAAC,CAAC,EAC1B,6BAA6B,CAAC,CAAC,CAAC,EAChC,sBAAsB,CAAC,CAAC,CAAC,EACzB,qBAAqB,CAAC,CAAC,CAAC;KAAG;IAG/B,KAAY,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG;QAC5D,SAAS,CAAC,EAAE,aAAa,CAAC;KAC3B,CAAC;IACF,UAAiB,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,EAAE,CACnD,SAAQ,qBAAqB,CAAC,CAAC,CAAC,EAC9B,qBAAqB,CAAC,CAAC,CAAC,EACxB,2BAA2B,CAAC,CAAC,CAAC,EAC9B,oBAAoB,CAAC,CAAC,CAAC;QACzB,SAAS,CAAC,EAAE,aAAa,CAAC;KAC3B;IAED,UAAiB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CACrD,SAAQ,eAAe,CAAC,CAAC,CAAC;QAC1B,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;KACzC;IAED,UAAiB,YAAY,CAAC,CAAC,SAAS,MAAM,CAC5C,SAAQ,kBAAkB,CAAC,CAAC,CAAC,EAC3B,iBAAiB,CAAC,CAAC,CAAC,EACpB,uBAAuB,CAAC,CAAC,CAAC,EAC1B,iBAAiB,CAAC,CAAC,CAAC,EACpB,oBAAoB,CAAC,CAAC,CAAC,EACvB,uBAAuB,CAAC,CAAC,CAAC,EAC1B,mBAAmB,CAAC,CAAC,CAAC,EACtB,kBAAkB,CAAC,CAAC,CAAC,EACrB,gBAAgB,CAAC,CAAC,CAAC,EACnB,qBAAqB,CAAC,CAAC,CAAC,EAIxB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;KAAG;CAC3B"} \ No newline at end of file diff --git a/dist/components/tablev2/react-table-config.js b/dist/components/tablev2/react-table-config.js new file mode 100644 index 0000000000..cb0ff5c3b5 --- /dev/null +++ b/dist/components/tablev2/react-table-config.js @@ -0,0 +1 @@ +export {}; diff --git a/dist/components/tablev2/useCheckbox.d.ts b/dist/components/tablev2/useCheckbox.d.ts new file mode 100644 index 0000000000..17298fc247 --- /dev/null +++ b/dist/components/tablev2/useCheckbox.d.ts @@ -0,0 +1,6 @@ +import { Hooks } from 'react-table'; +export declare const useCheckbox: { + (hooks: Hooks): void; + pluginName: string; +}; +//# sourceMappingURL=useCheckbox.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/useCheckbox.d.ts.map b/dist/components/tablev2/useCheckbox.d.ts.map new file mode 100644 index 0000000000..1f0f5182f7 --- /dev/null +++ b/dist/components/tablev2/useCheckbox.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useCheckbox.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/useCheckbox.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAmC,MAAM,aAAa,CAAC;AA+BrE,eAAO,MAAM,WAAW;YAAW,KAAK,CAAC,MAAM,CAAC;;CA2B/C,CAAC"} \ No newline at end of file diff --git a/dist/components/tablev2/useCheckbox.js b/dist/components/tablev2/useCheckbox.js new file mode 100644 index 0000000000..218f11735e --- /dev/null +++ b/dist/components/tablev2/useCheckbox.js @@ -0,0 +1,40 @@ +import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime"; +import { forwardRef, useEffect, useRef } from 'react'; +import styled from 'styled-components'; +import { Checkbox } from '../checkbox/Checkbox.component'; +const CheckBoxContainer = styled.div ` + display: flex; + align-items: center; + justify-content: center; + height: 100%; + width: 50px; +`; +const IndeterminateCheckbox = forwardRef(({ indeterminate, ...rest }, ref) => { + const defaultRef = useRef(null); + const resolvedRef = ref || defaultRef; + useEffect(() => { + resolvedRef.current.indeterminate = + !!indeterminate; + }, [resolvedRef, indeterminate]); + return (_jsx(_Fragment, { children: _jsx(Checkbox, { ref: resolvedRef, ...rest }) })); +}); +export const useCheckbox = (hooks) => { + hooks.visibleColumns.push((columns) => { + const test = [ + { + id: 'selection', + Header: ({ getToggleAllRowsSelectedProps }) => { + return (_jsx(CheckBoxContainer, { children: _jsx(IndeterminateCheckbox, { ...getToggleAllRowsSelectedProps() }) })); + }, + Cell: ({ row }) => { + return (_jsx(CheckBoxContainer, { children: _jsx(IndeterminateCheckbox, { ...row.getToggleRowSelectedProps() }) })); + }, + cellStyle: { width: '50px' }, + disableSortBy: true, + }, + ...columns, + ]; + return test; + }); +}; +useCheckbox.pluginName = 'useCheckbox'; diff --git a/dist/components/tablev2/useSyncedScroll.d.ts b/dist/components/tablev2/useSyncedScroll.d.ts new file mode 100644 index 0000000000..2e49eb0a96 --- /dev/null +++ b/dist/components/tablev2/useSyncedScroll.d.ts @@ -0,0 +1,7 @@ +import { Row } from 'react-table'; +import { FixedSizeList } from 'react-window'; +export default function useSyncedScroll = Record>(): { + headerRef: (element: HTMLDivElement) => void; + bodyRef: React.RefObject[]>>; +}; +//# sourceMappingURL=useSyncedScroll.d.ts.map \ No newline at end of file diff --git a/dist/components/tablev2/useSyncedScroll.d.ts.map b/dist/components/tablev2/useSyncedScroll.d.ts.map new file mode 100644 index 0000000000..40fb23d7e6 --- /dev/null +++ b/dist/components/tablev2/useSyncedScroll.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useSyncedScroll.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/useSyncedScroll.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/D;IACH,SAAS,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;CAC1D,CAmDA"} \ No newline at end of file diff --git a/dist/components/tablev2/useSyncedScroll.js b/dist/components/tablev2/useSyncedScroll.js new file mode 100644 index 0000000000..62bdabfc22 --- /dev/null +++ b/dist/components/tablev2/useSyncedScroll.js @@ -0,0 +1,41 @@ +import { useEffect, useCallback, useRef } from 'react'; +import { useTableContext } from './Tablev2.component'; +export default function useSyncedScroll() { + const { syncScrollListener, setSyncScrollListener } = useTableContext(); + const headerRef = useCallback((element) => { + if (element) { + const callback = (event) => { + if (element && event) { + element.scrollTo({ + left: event.target.scrollLeft, + top: 0, + }); + } + }; + if (!syncScrollListener) { + setSyncScrollListener(() => { + return callback; + }); + } + } + }, [syncScrollListener]); + const bodyRef = useRef(null); + useEffect(() => { + if (bodyRef.current && syncScrollListener) { + /* + We intentionally use _outerRef prop here despite the fact that it is + internal use only and not typed, as it is the only way for us to access to the scrollable element + */ + //@ts-expect-error + bodyRef.current._outerRef.addEventListener('scroll', syncScrollListener); + } + return () => { + //@ts-expect-error + if (bodyRef.current && bodyRef.current._outerRef) { + //@ts-expect-error + bodyRef.current._outerRef.removeEventListener('scroll', syncScrollListener); + } + }; + }, [bodyRef.current, syncScrollListener]); + return { headerRef, bodyRef }; +} diff --git a/dist/components/tabsv2/ScrollButton.d.ts b/dist/components/tabsv2/ScrollButton.d.ts new file mode 100644 index 0000000000..241b0bf6b4 --- /dev/null +++ b/dist/components/tabsv2/ScrollButton.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +type Props = { + direction: 'left' | 'right'; + onClick: (arg0: React.SyntheticEvent) => void; +}; +declare const ScrollButton: React.ForwardRefExoticComponent>; +export { ScrollButton }; +//# sourceMappingURL=ScrollButton.d.ts.map \ No newline at end of file diff --git a/dist/components/tabsv2/ScrollButton.d.ts.map b/dist/components/tabsv2/ScrollButton.d.ts.map new file mode 100644 index 0000000000..370c9f5792 --- /dev/null +++ b/dist/components/tabsv2/ScrollButton.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ScrollButton.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tabsv2/ScrollButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA0B1B,KAAK,KAAK,GAAG;IACX,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;CAC/D,CAAC;AACF,QAAA,MAAM,YAAY,uEAOhB,CAAC;AACH,OAAO,EAAE,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/tabsv2/ScrollButton.js b/dist/components/tabsv2/ScrollButton.js new file mode 100644 index 0000000000..91e19d51c8 --- /dev/null +++ b/dist/components/tabsv2/ScrollButton.js @@ -0,0 +1,32 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import React from 'react'; +import styled from 'styled-components'; +import { zIndex } from '../../style/theme'; +import { spacing } from '../../spacing'; +import { getThemePropSelector } from '../../utils'; +import { Icon } from '../icon/Icon.component'; +const StyledScrollButton = styled.div ` + display: flex; + justify-content: center; + align-items: center; + width: ${spacing.r24}; + z-index: ${zIndex.scrollbarButton}; + color: ${getThemePropSelector('textSecondary')}; + background-color: ${getThemePropSelector('backgroundLevel3')}; + box-shadow: 0px 0px ${spacing.r2} rgba(0, 0, 0, 0.75); + box-sizing: border-box; + border: ${spacing.r1} solid transparent; + cursor: pointer; + + &:hover { + border-radius: ${spacing.r2}; + box-shadow: none; + border: ${spacing.r1} solid ${getThemePropSelector('infoPrimary')}; + } +`; +const ScrollButton = React.forwardRef(({ direction, onClick }, ref) => { + return ( + // @ts-ignore + _jsx(StyledScrollButton, { direction: direction, onClick: onClick, ref: ref, children: _jsx(Icon, { name: `Chevron-${direction}` }) })); +}); +export { ScrollButton }; diff --git a/dist/components/tabsv2/StyledTabs.d.ts b/dist/components/tabsv2/StyledTabs.d.ts new file mode 100644 index 0000000000..aa55f7e7dd --- /dev/null +++ b/dist/components/tabsv2/StyledTabs.d.ts @@ -0,0 +1,19 @@ +export declare const TabBar: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const TabItem: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, { + selected?: boolean; + activeTabColor?: string; + activeTabSeparator?: string; + inactiveTabColor?: string; + tabHoverColor?: string; +}, never>; +export declare const TabsContainer: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, { + tabLineColor?: string; + separatorColor?: string; +}, never>; +export declare const TabContent: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, { + tabContentColor?: string; + withoutPadding?: boolean; +}, never>; +export declare const ScrollableContainer: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +export declare const TabsScroller: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>; +//# sourceMappingURL=StyledTabs.d.ts.map \ No newline at end of file diff --git a/dist/components/tabsv2/StyledTabs.d.ts.map b/dist/components/tabsv2/StyledTabs.d.ts.map new file mode 100644 index 0000000000..a712ae0b84 --- /dev/null +++ b/dist/components/tabsv2/StyledTabs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"StyledTabs.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tabsv2/StyledTabs.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,yGAGlB,CAAC;AACF,eAAO,MAAM,OAAO;eACP,OAAO;qBACD,MAAM;yBACF,MAAM;uBACR,MAAM;oBACT,MAAM;SA6CvB,CAAC;AACF,eAAO,MAAM,aAAa;mBACT,MAAM;qBACJ,MAAM;SA0BxB,CAAC;AACF,eAAO,MAAM,UAAU;sBACH,MAAM;qBACP,OAAO;SAUzB,CAAC;AACF,eAAO,MAAM,mBAAmB,yGAE/B,CAAC;AACF,eAAO,MAAM,YAAY,yGAYxB,CAAC"} \ No newline at end of file diff --git a/dist/components/tabsv2/StyledTabs.js b/dist/components/tabsv2/StyledTabs.js new file mode 100644 index 0000000000..80b6214ea9 --- /dev/null +++ b/dist/components/tabsv2/StyledTabs.js @@ -0,0 +1,100 @@ +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +export const TabBar = styled.div ` + display: flex; + height: ${spacing.r40}; +`; +export const TabItem = styled.div ` + display: flex; + align-items: center; + padding: 0 ${spacing.r24} 0 ${spacing.r24}; + border-radius: ${spacing.r4} ${spacing.r4} 0 0; + border: ${spacing.r1} solid transparent; + min-width: 5rem; + + &:focus-visible { + outline: 0; + position: relative; + border: ${spacing.r1} dashed ${(props) => props.theme.selectedActive}; + } + + &:focus-within { + outline: 0; + } + + ${(props) => { + const { highlight, backgroundLevel3, backgroundLevel4, selectedActive } = props.theme; + return props.selected + ? ` + background-color: ${props.activeTabColor || backgroundLevel4}; + &:after { + content: ""; + background: ${props.activeTabSeparator || selectedActive}; + position: absolute; + border-radius: ${spacing.r2} ${spacing.r2} 0 0; + bottom: 0; + right: 0; + left: calc(50% - ${spacing.r16}); + height: ${spacing.r2}; + width: ${spacing.r32}; + } + ` + : ` + background-color: ${props.inactiveTabColor || backgroundLevel3}; + &:hover { + cursor: pointer; + border: ${spacing.r1} solid ${props.tabHoverColor || highlight}; + } + `; +}} +`; +export const TabsContainer = styled.div ` + height: 100%; + width: 100%; + contain: layout; + display: flex; + flex-direction: column; + background-color: ${(props) => props.tabLineColor || props.theme.backgroundLevel3}; + + & ${TabItem} { + display: flex; + justify-content: center; + position: relative; + } + + & ${TabItem}::before { + content: ''; + background: ${(props) => props.separatorColor || props.theme.infoSecondary}; + position: absolute; + bottom: 25%; + right: 0; + height: ${spacing.r16}; + width: 1px; + margin-right: -1px; + } +`; +export const TabContent = styled.div ` + margin: 0; + padding: ${(props) => (props.withoutPadding ? '0' : spacing.r16)}; + display: block; + width: 100%; + height: calc(100% - ${spacing.r40}); + box-sizing: border-box; + background-color: ${(props) => props.tabContentColor || props.theme.backgroundLevel4}; +`; +export const ScrollableContainer = styled.div ` + display: flex; +`; +export const TabsScroller = styled.div ` + position: relative; + display: inline-flex; + flex: 1 1 auto; + white-space: nowrap; + width: 100%; + scrollbar-width: none; // Firefox + &::-webkit-scrollbar { + display: none; // Safari + Chrome + } + overflow-x: auto; + overflow-y: hidden; +`; diff --git a/dist/components/tabsv2/Tab.d.ts b/dist/components/tabsv2/Tab.d.ts new file mode 100644 index 0000000000..86433923e1 --- /dev/null +++ b/dist/components/tabsv2/Tab.d.ts @@ -0,0 +1,17 @@ +export type Query = Record; +export type TabProps = { + path: string; + query?: Query; + label: JSX.Element | string; + icon?: JSX.Element; + textBadge?: JSX.Element; + children: JSX.Element; + className?: string; + exact?: boolean; + strict?: boolean; + sensitive?: boolean; + withoutPadding?: boolean; +}; +declare function Tab(_: TabProps): null; +export { Tab }; +//# sourceMappingURL=Tab.d.ts.map \ No newline at end of file diff --git a/dist/components/tabsv2/Tab.d.ts.map b/dist/components/tabsv2/Tab.d.ts.map new file mode 100644 index 0000000000..a5f2ad90cd --- /dev/null +++ b/dist/components/tabsv2/Tab.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Tab.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tabsv2/Tab.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC3C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACxB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,iBAAS,GAAG,CAAC,CAAC,EAAE,QAAQ,QAQvB;AAED,OAAO,EAAE,GAAG,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/tabsv2/Tab.js b/dist/components/tabsv2/Tab.js new file mode 100644 index 0000000000..60d278d298 --- /dev/null +++ b/dist/components/tabsv2/Tab.js @@ -0,0 +1,10 @@ +import { useContext } from 'react'; +import { TabsContext } from './Tabsv2.component'; +function Tab(_) { + const context = useContext(TabsContext); + if (!context) { + throw new Error('Tab cannot be rendered outside the Tabs component'); + } + return null; +} +export { Tab }; diff --git a/dist/components/tabsv2/Tabsv2.component.d.ts b/dist/components/tabsv2/Tabsv2.component.d.ts new file mode 100644 index 0000000000..c74068321e --- /dev/null +++ b/dist/components/tabsv2/Tabsv2.component.d.ts @@ -0,0 +1,21 @@ +import React, { ReactElement } from 'react'; +import { Tab } from './Tab'; +import { TabProps } from './Tab'; +type TabsProps = { + activeTabColor?: string; + activeTabSeparator?: string; + tabLineColor?: string; + inactiveTabColor?: string; + tabContentColor?: string; + separatorColor?: string; + tabHoverColor?: string; + children: ReactElement[]; + className?: string; +}; +export declare const TabsContext: React.Context; +declare function Tabs({ activeTabColor, activeTabSeparator, tabLineColor, inactiveTabColor, tabContentColor, separatorColor, tabHoverColor, children, className, ...rest }: TabsProps): import("react/jsx-runtime").JSX.Element; +declare namespace Tabs { + var Tab: typeof import("./Tab").Tab; +} +export { Tabs, Tab }; +//# sourceMappingURL=Tabsv2.component.d.ts.map \ No newline at end of file diff --git a/dist/components/tabsv2/Tabsv2.component.d.ts.map b/dist/components/tabsv2/Tabsv2.component.d.ts.map new file mode 100644 index 0000000000..2115aa940b --- /dev/null +++ b/dist/components/tabsv2/Tabsv2.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Tabsv2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tabsv2/Tabsv2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAKZ,YAAY,EACb,MAAM,OAAO,CAAC;AAmBf,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAS,MAAM,OAAO,CAAC;AAKxC,KAAK,SAAS,GAAG;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AACF,eAAO,MAAM,WAAW,wBAAgC,CAAC;AAMzD,iBAAS,IAAI,CAAC,EACZ,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,aAAa,EACb,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,SAAS,2CA+LX;kBA1MQ,IAAI;;;AA8Mb,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/tabsv2/Tabsv2.component.js b/dist/components/tabsv2/Tabsv2.component.js new file mode 100644 index 0000000000..fb8f768e5b --- /dev/null +++ b/dist/components/tabsv2/Tabsv2.component.js @@ -0,0 +1,88 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import React, { createContext, useEffect, useState, useCallback, } from 'react'; +import { TabBar, ScrollableContainer, TabContent, TabItem, TabsContainer, TabsScroller, } from './StyledTabs'; +import { useHistory, useLocation, useRouteMatch, matchPath, Route, } from 'react-router-dom'; +import { SecondaryText, BasicText, EmphaseText } from '../text/Text.component'; +import { ScrollButton } from './ScrollButton'; +import { Tab } from './Tab'; +import { useScrollingTabs } from './useScrollingTabs'; +import { ButtonIcon } from '../buttonv2/Buttonv2.component'; +import styled from 'styled-components'; +export const TabsContext = createContext(false); +const TabIcon = styled(ButtonIcon) ` + color: ${(props) => props.theme.textSecondary}; +`; +function Tabs({ activeTabColor, activeTabSeparator, tabLineColor, inactiveTabColor, tabContentColor, separatorColor, tabHoverColor, children, className, ...rest }) { + const location = useLocation(); + const history = useHistory(); + const { url } = useRouteMatch(); + const [selectedTabIndex, setSelectedTabIndex] = useState(null); + const queryURL = new URLSearchParams(location.search); + const filteredTabsChildren = React.Children.toArray(children).filter((child) => React.isValidElement(child) && child.type === Tab); + const matchQuery = useCallback((query) => { + for (const key of Object.keys(query)) { + // To support the case of {tab:null} + if (queryURL.get(key) === null && !query[key]) { + return true; + } + if (!(queryURL.has(key) && queryURL.get(key) === query[key])) + return false; + } + return true; + }, [queryURL]); + const serialize = (query) => { + if (!query) { + return ''; + } + else { + const o = Object.fromEntries(Object.entries(query).filter(([_, v]) => v != null)); + //$FlowFixMe + return '?' + new URLSearchParams(o).toString(); + } + }; + const getPushHistoryPath = (path, query) => { + if (path.startsWith('/')) { + return `${path}${serialize(query)}`; + } + return `${url}/${path}${serialize(query)}`; + }; + useEffect(() => { + let hasSelectedTab = false; + filteredTabsChildren.forEach((child, index) => { + const isSelected = !!matchPath(location.pathname, { + path: child.props.path.startsWith('/') + ? child.props.path + : url + '/' + child.props.path, + exact: child.props.exact, + strict: child.props.strict, + sensitive: child.props.sensitive, + }) && (child.props.query ? matchQuery(child.props.query) : true); + if (isSelected) { + setSelectedTabIndex(index); + hasSelectedTab = true; + } + }); + if (!hasSelectedTab) + setSelectedTabIndex(null); + }, [location.pathname, filteredTabsChildren, matchQuery]); + const { scrollButtonEndRef, scrollButtonStartRef, tabsListRef, tabsRef, handleStartScrollClick, handleEndScrollClick, handleTabsScroll, handleKeyDown, displayScroll, } = useScrollingTabs(selectedTabIndex); + const tabItems = filteredTabsChildren.map((child, index) => { + const { path, query, label, textBadge, children, icon, ...childRest } = child.props; + const isSelected = selectedTabIndex === index; + return (_jsxs(TabItem, { className: `sc-tabs-item ${isSelected ? 'selected' : ''}`, role: "tab", onClick: () => history.push(getPushHistoryPath(path, query)), selected: isSelected, tabHoverColor: tabHoverColor, inactiveTabColor: inactiveTabColor, activeTabColor: activeTabColor, activeTabSeparator: activeTabSeparator, tabIndex: isSelected ? 0 : -1, onKeyDown: (event) => { + if (event.key === ' ' || + event.key === 'Enter' || + event.key === 'Spacebar') { + event.preventDefault(); + history.push(getPushHistoryPath(path, query)); + } + }, ...childRest, children: [icon && _jsx(TabIcon, { label: label, children: icon }), isSelected ? (_jsx(BasicText, { children: label })) : (_jsx(SecondaryText, { children: label })), textBadge && _jsx(EmphaseText, { children: textBadge })] }, index)); + }); + return (_jsx(TabsContext.Provider, { value: true, children: _jsxs(TabsContainer, { style: { containerType: 'size' }, className: ['sc-tabs', className].join(' '), tabLineColor: tabLineColor, separatorColor: separatorColor, ...rest, children: [_jsxs(ScrollableContainer, { children: [displayScroll.start && (_jsx(ScrollButton, { ref: scrollButtonStartRef, direction: "left", onClick: handleStartScrollClick })), _jsx(TabsScroller, { ref: tabsRef, onScroll: handleTabsScroll, children: _jsx(TabBar, { onKeyDown: handleKeyDown, ref: tabsListRef, className: "sc-tabs-bar", role: "tablist", children: tabItems }) }), displayScroll.end && (_jsx(ScrollButton, { ref: scrollButtonEndRef, direction: "right", onClick: handleEndScrollClick }))] }), filteredTabsChildren.map((tab, index) => (_jsx(Route, { exact: tab.props.exact, sensitive: tab.props.sensitive, strict: tab.props.strict, path: tab.props.path.startsWith('/') + ? tab.props.path + : url + '/' + tab.props.path, children: !tab.props.query || + (tab.props.query && matchQuery(tab.props.query)) ? (_jsx(TabContent, { className: "sc-tabs-item-content", tabContentColor: tabContentColor, withoutPadding: tab.props.withoutPadding, children: tab.props.children })) : (_jsx(_Fragment, {})) }, index)))] }) })); +} +Tabs.Tab = Tab; +// re-export Tab +export { Tabs, Tab }; diff --git a/dist/components/tabsv2/useScrollingTabs.d.ts b/dist/components/tabsv2/useScrollingTabs.d.ts new file mode 100644 index 0000000000..8be8041f9b --- /dev/null +++ b/dist/components/tabsv2/useScrollingTabs.d.ts @@ -0,0 +1,16 @@ +declare const useScrollingTabs: (selectedTabIndex: number | null | undefined) => { + scrollButtonStartRef: import("react").MutableRefObject; + scrollButtonEndRef: import("react").MutableRefObject; + tabsRef: import("react").MutableRefObject; + tabsListRef: import("react").RefObject; + handleKeyDown: (event: React.KeyboardEvent) => void; + handleTabsScroll: () => void; + handleStartScrollClick: () => void; + handleEndScrollClick: () => void; + displayScroll: { + start: boolean; + end: boolean; + }; +}; +export { useScrollingTabs }; +//# sourceMappingURL=useScrollingTabs.d.ts.map \ No newline at end of file diff --git a/dist/components/tabsv2/useScrollingTabs.d.ts.map b/dist/components/tabsv2/useScrollingTabs.d.ts.map new file mode 100644 index 0000000000..45a6c4ff15 --- /dev/null +++ b/dist/components/tabsv2/useScrollingTabs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useScrollingTabs.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tabsv2/useScrollingTabs.ts"],"names":[],"mappings":"AAmIA,QAAA,MAAM,gBAAgB,qBAAsB,MAAM,GAAG,IAAI,GAAG,SAAS;;;;;2BA0JrC,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC;;;;;;;;CA+ClE,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/tabsv2/useScrollingTabs.js b/dist/components/tabsv2/useScrollingTabs.js new file mode 100644 index 0000000000..2f3c50b9fb --- /dev/null +++ b/dist/components/tabsv2/useScrollingTabs.js @@ -0,0 +1,261 @@ +/* +The Tabs component uses a lot of the code from Material-UI Scrollable Tabs to have the same behavior as it. +Here is the license of material-ui: + +The MIT License (MIT) + +Copyright (c) 2014 Call-Em-All + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +function easeInOutSin(time) { + return (1 + Math.sin(Math.PI * time - Math.PI / 2)) / 2; +} +function animate(property, element, to) { + const duration = 1000; // standard + let start = null; + const from = element[property]; + let cancelled = false; + const cancel = () => { + cancelled = true; + }; + const step = (timestamp) => { + if (cancelled) { + return; + } + if (start === null) { + start = timestamp; + } + const time = Math.min(1, (timestamp - start) / duration); + element[property] = easeInOutSin(time) * (to - from) + from; + if (time >= 1) { + return; + } + requestAnimationFrame(step); + }; + if (from === to) { + return cancel; + } + requestAnimationFrame(step); + return cancel; +} +const nextItem = (list, item) => { + if (list === item) { + return list.firstChild; + } + if (item && item.nextElementSibling) { + return item.nextElementSibling; + } + return list.firstChild; +}; +const previousItem = (list, item) => { + if (list === item) { + return list.lastChild; + } + if (item && item.previousElementSibling) { + return item.previousElementSibling; + } + return list.lastChild; +}; +const moveFocus = (list, currentFocus, traversalFunction) => { + let wrappedOnce = false; + let nextFocus = traversalFunction(list, currentFocus); + while (nextFocus) { + // Prevent infinite loop. + if (nextFocus === list.firstChild) { + if (wrappedOnce) { + return; + } + wrappedOnce = true; + } + if (!nextFocus.hasAttribute('tabindex')) { + // Move to the next element. + nextFocus = traversalFunction(list, nextFocus); + } + else { + nextFocus.focus(); + return; + } + } +}; +const useScrollingTabs = (selectedTabIndex) => { + const [displayScroll, setDisplayScroll] = useState({ + start: false, + end: false, + }); + const scrollButtonEndRef = useRef(null); + const scrollButtonStartRef = useRef(null); + const tabsListRef = useRef(null); + const tabsRef = useRef(null); + const scroll = (scrollValue) => { + animate('scrollLeft', tabsRef.current, scrollValue); + }; + const moveTabsScroll = (delta) => { + let scrollValue = tabsRef.current.scrollLeft; + scrollValue += delta; + scroll(scrollValue); + }; + const getScrollSize = (isStart = false) => { + if (!tabsListRef.current) + return 0; + const fullContainerSize = tabsListRef.current.clientWidth; + const containerSize = tabsRef.current.clientWidth; + let totalSize = 0; + const children = Array.from(tabsListRef.current.children); + for (let i = 0; i < children.length; i += 1) { + const tab = children[i]; + if (totalSize + tab.clientWidth > containerSize) { + break; + } + totalSize += tab.clientWidth; + } + const cornerChild = isStart ? children[0] : children[children.length - 1]; + if (totalSize + + tabsRef.current.scrollLeft + + containerSize + + cornerChild.clientWidth > + fullContainerSize) { + totalSize += cornerChild.clientWidth; + } + return totalSize; + }; + const handleStartScrollClick = () => { + moveTabsScroll(-1 * getScrollSize(true)); + }; + const handleEndScrollClick = () => { + moveTabsScroll(getScrollSize(false)); + }; + const getTabsMeta = useCallback(() => { + const tabsNode = tabsRef.current; + let tabsMeta; + if (tabsNode) { + const rect = tabsNode.getBoundingClientRect(); + tabsMeta = { + scrollLeft: tabsNode.scrollLeft, + left: rect.left, + right: rect.right, + }; + } + let selectedTabMeta; + if (tabsNode && tabsListRef.current && selectedTabIndex) { + const children = tabsListRef.current.children; + if (children.length > 0) { + const tab = children[selectedTabIndex]; + selectedTabMeta = tab ? tab.getBoundingClientRect() : null; + } + } + return { + tabsMeta, + selectedTabMeta, + }; + }, [selectedTabIndex]); + const scrollSelectedIntoView = useCallback(() => { + const { tabsMeta, selectedTabMeta } = getTabsMeta(); + if (!selectedTabMeta || !tabsMeta) + return; + if (selectedTabMeta.left < tabsMeta.left) { + // left side of button is out of view + const nextScrollStart = tabsMeta.scrollLeft + (selectedTabMeta.left - tabsMeta.left); + scroll(nextScrollStart); + } + else if (selectedTabMeta.right > tabsMeta.right) { + // right side of button is out of view + let nextScrollStart = tabsMeta.scrollLeft + (selectedTabMeta.right - tabsMeta.right); + if (scrollButtonEndRef.current && + ((displayScroll.start && !displayScroll.end) || + (!displayScroll.start && displayScroll.end))) { + nextScrollStart += + scrollButtonEndRef.current.getBoundingClientRect().width; + } + scroll(nextScrollStart); + } + }, // we do not want to re-trigger this function if display.start / display.end are modified + // eslint-disable-next-line react-hooks/exhaustive-deps + [getTabsMeta]); + const updateScrollButtonState = useCallback(() => { + if (tabsRef.current) { + const { scrollLeft, scrollWidth, clientWidth } = tabsRef.current; + let showStartScroll = scrollLeft > 1; + let showEndScroll = scrollLeft < scrollWidth - clientWidth - 1; + if (showStartScroll !== displayScroll.start || + showEndScroll !== displayScroll.end) { + setDisplayScroll({ + start: showStartScroll, + end: showEndScroll, + }); + } + } + }, [displayScroll.end, displayScroll.start]); + useEffect(() => { + window.addEventListener('resize', updateScrollButtonState); + return () => { + window.removeEventListener('resize', updateScrollButtonState); + }; + }, [updateScrollButtonState]); + const handleTabsScroll = useMemo(() => () => updateScrollButtonState(), [updateScrollButtonState]); + useEffect(() => { + updateScrollButtonState(); + }); + // scroll to selected tab on first render + useEffect(() => { + scrollSelectedIntoView(); + }, [scrollSelectedIntoView, selectedTabIndex]); + const handleKeyDown = (event) => { + const list = tabsListRef.current; + const ownerDocument = (list && list.ownerDocument) || document; + const currentFocus = ownerDocument.activeElement; + const role = currentFocus === null || currentFocus === void 0 ? void 0 : currentFocus.getAttribute('role'); + if (role !== 'tab' || !list) { + return; + } + switch (event.key) { + case 'ArrowLeft': + event.preventDefault(); + moveFocus(list, currentFocus, previousItem); + break; + case 'ArrowRight': + event.preventDefault(); + moveFocus(list, currentFocus, nextItem); + break; + case 'Home': + event.preventDefault(); + moveFocus(list, null, nextItem); + break; + case 'End': + event.preventDefault(); + moveFocus(list, null, previousItem); + break; + default: + break; + } + }; + return { + scrollButtonStartRef, + scrollButtonEndRef, + tabsRef, + tabsListRef, + handleKeyDown, + handleTabsScroll, + handleStartScrollClick, + handleEndScrollClick, + displayScroll, + }; +}; +export { useScrollingTabs }; diff --git a/dist/components/text/Text.component.d.ts b/dist/components/text/Text.component.d.ts new file mode 100644 index 0000000000..3ecf56417e --- /dev/null +++ b/dist/components/text/Text.component.d.ts @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { CoreUITheme } from '../../style/theme'; +type Status = 'unknown' | 'healthy' | 'warning' | 'critical'; +type Props = { + children: React.ReactNode | string; + status?: Status; + id?: string; +}; +export declare const SmallerEmphaseTextStyle: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, { + statusColor: string; +}, never>; +export declare function BasicText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function SecondaryText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function LargerText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function EmphaseText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function StatusText({ children, status, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function LargeText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function SmallerText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function SmallerSecondaryText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function SmallerEmphaseText({ children, status, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare function ChartTitleText({ children, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare const GentleEmphaseSecondaryText: import("styled-components").StyledComponent; +export declare const Text: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, { + variant?: "ChartTitle" | "Basic" | "Smaller" | "Larger" | "Large"; + color?: keyof CoreUITheme; + isEmphazed?: boolean; + isGentleEmphazed?: boolean; +}, never>; +export declare const Link: import("styled-components").StyledComponent<"a", import("styled-components").DefaultTheme, {}, never>; +export {}; +//# sourceMappingURL=Text.component.d.ts.map \ No newline at end of file diff --git a/dist/components/text/Text.component.d.ts.map b/dist/components/text/Text.component.d.ts.map new file mode 100644 index 0000000000..0c81090634 --- /dev/null +++ b/dist/components/text/Text.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Text.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/text/Text.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,KAAK,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAC7D,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAsDF,eAAO,MAAM,uBAAuB;iBACrB,MAAM;SAIpB,CAAC;AAIF,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAErD;AACD,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAEzD;AACD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAEtD;AACD,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAEvD;AACD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAO9D;AACD,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAErD;AACD,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAEvD;AACD,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAIhE;AACD,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAOtE;AAED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAE1D;AACD,eAAO,MAAM,0BAA0B;iBACxB,OAAO;SAUrB,CAAC;AAEF,eAAO,MAAM,IAAI;cACL,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO;YACzD,MAAM,WAAW;iBACZ,OAAO;uBACD,OAAO;SA2C3B,CAAC;AAEF,eAAO,MAAM,IAAI,uGAchB,CAAC"} \ No newline at end of file diff --git a/dist/components/text/Text.component.js b/dist/components/text/Text.component.js new file mode 100644 index 0000000000..0ac77491c1 --- /dev/null +++ b/dist/components/text/Text.component.js @@ -0,0 +1,154 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { FocusVisibleStyle } from '../buttonv2/Buttonv2.component'; +const BasicTextStyle = styled.span ` + color: ${(props) => props.theme.textPrimary}; + font-size: 1rem; + line-height: ${spacing.r24}; + font-weight: 400; +`; +const SecondaryTextStyle = styled(BasicTextStyle) ` + color: ${(props) => props.theme.textSecondary}; +`; +const LargerTextStyle = styled(BasicTextStyle) ` + font-size: 1.43rem; + line-height: 1.5; +`; +const EmphaseTextStyle = styled(BasicTextStyle) ` + font-weight: 700; +`; +const StatusTextStyle = styled(BasicTextStyle) ` + color: ${(props) => props.theme[`${props.statusColor}`]}; +`; +const LargetStyle = styled(BasicTextStyle) ` + font-size: 1.14rem; + line-height: 1.5; +`; +const SmallerTextStyle = styled(BasicTextStyle) ` + font-size: 0.71rem; + line-height: 1.4; + letter-spacing: 2%; // to be defined, percentage value is not valid +`; +const SmallerSecondaryTextStyle = styled(SmallerTextStyle) ` + color: ${(props) => props.theme.textSecondary}; +`; +const getStatusColor = (status) => { + let statusColor; + switch (status) { + case 'healthy': + statusColor = 'statusHealthy'; + break; + case 'warning': + statusColor = 'statusWarning'; + break; + case 'critical': + statusColor = 'statusCritical'; + break; + default: + statusColor = 'textSecondary'; + } + return statusColor; +}; +export const SmallerEmphaseTextStyle = styled(SmallerTextStyle) ` + font-weight: 700; + color: ${(props) => props.theme[`${props.statusColor}`]}; +`; +const ChartTitleTextStyle = styled(BasicTextStyle) ` + letter-spacing: ${spacing.r2}; +`; +export function BasicText({ children, ...rest }) { + return _jsx(BasicTextStyle, { ...rest, children: children }); +} +export function SecondaryText({ children, ...rest }) { + return _jsx(SecondaryTextStyle, { ...rest, children: children }); +} +export function LargerText({ children, ...rest }) { + return _jsx(LargerTextStyle, { ...rest, children: children }); +} +export function EmphaseText({ children, ...rest }) { + return _jsx(EmphaseTextStyle, { ...rest, children: children }); +} +export function StatusText({ children, status, ...rest }) { + const statusColor = getStatusColor(status); + return (_jsx(StatusTextStyle, { statusColor: statusColor, ...rest, children: children })); +} +export function LargeText({ children, ...rest }) { + return _jsx(LargetStyle, { ...rest, children: children }); +} +export function SmallerText({ children, ...rest }) { + return _jsx(SmallerTextStyle, { ...rest, children: children }); +} +export function SmallerSecondaryText({ children, ...rest }) { + return (_jsx(SmallerSecondaryTextStyle, { ...rest, children: children })); +} +export function SmallerEmphaseText({ children, status, ...rest }) { + const statusColor = getStatusColor(status); + return (_jsx(SmallerEmphaseTextStyle, { statusColor: statusColor, ...rest, children: children })); +} +export function ChartTitleText({ children, ...rest }) { + return _jsx(ChartTitleTextStyle, { ...rest, children: children }); +} +export const GentleEmphaseSecondaryText = styled(SecondaryText) ` + font-style: italic; + ${(props) => props.alignRight + ? ` + text-align: right; + display: block; + ` + : ''} +`; +export const Text = styled.span ` + color: ${(props) => props.theme[props.color || 'textPrimary']}; + ${(props) => props.variant === 'Larger' + ? ` + font-size: 1.43rem; + line-height: 1.5; + ` + : props.variant === 'Large' + ? ` + font-size: 1.14rem; + line-height: 1.5; + ` + : props.variant === 'Smaller' + ? ` + font-size: 0.71rem; + line-height: 1.4; + letter-spacing: 2%;// to be defined, percentage value is not valid + ` + : ` + font-size: 1rem; + line-height: ${spacing.r24}; + `} + + ${(props) => props.isEmphazed + ? ` + font-weight: 700; + ` + : ` + font-weight: 400; + `} + + ${(props) => props.isGentleEmphazed + ? ` + font-style: italic; + ` + : ``} + + ${(props) => props.variant === 'ChartTitle' && `letter-spacing: ${spacing.r2};`} +`; +export const Link = styled.a ` + font-size: 1rem; + line-height: ${spacing.r24}; + color: ${(props) => props.theme.textLink}; + cursor: pointer; + text-decoration-line: none; + width: fit-content; + &:hover { + text-decoration-line: underline; + } + // :focus-visible is the keyboard-only version of :focus + &:focus-visible { + ${FocusVisibleStyle} + } +`; diff --git a/dist/components/textarea/TextArea.component.d.ts b/dist/components/textarea/TextArea.component.d.ts new file mode 100644 index 0000000000..3fffae9d39 --- /dev/null +++ b/dist/components/textarea/TextArea.component.d.ts @@ -0,0 +1,10 @@ +import React, { CSSProperties } from 'react'; +type TextAreaVariant = 'code' | 'text'; +type RefType = HTMLTextAreaElement | null; +export declare const TextArea: React.ForwardRefExoticComponent & { + variant?: TextAreaVariant; + width?: CSSProperties["width"]; + height?: CSSProperties["height"]; +} & React.RefAttributes>; +export {}; +//# sourceMappingURL=TextArea.component.d.ts.map \ No newline at end of file diff --git a/dist/components/textarea/TextArea.component.d.ts.map b/dist/components/textarea/TextArea.component.d.ts.map new file mode 100644 index 0000000000..8d86b74e3d --- /dev/null +++ b/dist/components/textarea/TextArea.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TextArea.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/textarea/TextArea.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,aAAa,EAGd,MAAM,OAAO,CAAC;AAIf,KAAK,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AAMvC,KAAK,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAAC;AA2F1C,eAAO,MAAM,QAAQ;cA/FT,eAAe;YACjB,aAAa,CAAC,OAAO,CAAC;aACrB,aAAa,CAAC,QAAQ,CAAC;iCA6FiC,CAAC"} \ No newline at end of file diff --git a/dist/components/textarea/TextArea.component.js b/dist/components/textarea/TextArea.component.js new file mode 100644 index 0000000000..ce899f3f29 --- /dev/null +++ b/dist/components/textarea/TextArea.component.js @@ -0,0 +1,60 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { forwardRef, } from 'react'; +import styled, { css } from 'styled-components'; +import { spacing } from '../../spacing'; +const TextAreaContainer = styled.textarea ` + padding: ${spacing.r12} ${spacing.r8}; + border-radius: 4px; + resize: vertical; + font-family: ${(props) => props.variant === 'code' ? 'Courier New' : 'Lato'}; + font-size: ${spacing.f14}; + + ${(props) => props.disabled && + css ` + opacity: 0.5; + cursor: not-allowed; + `} + + ${(props) => props.width && + css ` + width: ${props.width}; + `} + + ${(props) => props.height && + css ` + height: ${props.height}; + `} + + &:placeholder-shown { + font-style: italic; + } + &::placeholder { + color: ${(props) => props.theme.textSecondary}; + } + &:hover { + ${(props) => !props.disabled && + `border: ${spacing.r1} solid ${props.theme.infoPrimary};`} + } + &:focus { + border: ${spacing.r1} solid ${(props) => props.theme.infoPrimary}; + } + ${(props) => { + const { border, textSecondary, backgroundLevel1, selectedActive } = props.theme; + return css ` + border-color: ${border}; + color: ${textSecondary}; + background: ${backgroundLevel1}; + &:focus { + border-color: ${selectedActive}; + outline: none; + } + `; +}} +`; +function TextAreaElement({ rows = 3, cols = 20, width, height, variant = 'code', ...rest }, ref) { + if (width || height) { + return (_jsx(TextAreaContainer, { className: "sc-textarea", width: width, height: height, variant: variant, ...rest, ref: ref })); + } + return (_jsx(TextAreaContainer, { className: "sc-textarea", rows: rows, cols: cols, variant: variant, ...rest, ref: ref })); +} +export const TextArea = forwardRef(TextAreaElement); diff --git a/dist/components/textbadge/TextBadge.component.d.ts b/dist/components/textbadge/TextBadge.component.d.ts new file mode 100644 index 0000000000..b016c09ff4 --- /dev/null +++ b/dist/components/textbadge/TextBadge.component.d.ts @@ -0,0 +1,10 @@ +import React from 'react'; +type TextBadgeVariant = 'statusHealthy' | 'statusWarning' | 'statusCritical' | 'infoPrimary' | 'infoSecondary' | 'selectedActive'; +type Props = { + text: string; + className?: string; + variant?: TextBadgeVariant; +} & React.HTMLAttributes; +export declare function TextBadge({ text, variant, className, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export {}; +//# sourceMappingURL=TextBadge.component.d.ts.map \ No newline at end of file diff --git a/dist/components/textbadge/TextBadge.component.d.ts.map b/dist/components/textbadge/TextBadge.component.d.ts.map new file mode 100644 index 0000000000..15a7bda297 --- /dev/null +++ b/dist/components/textbadge/TextBadge.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TextBadge.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/textbadge/TextBadge.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,KAAK,gBAAgB,GACjB,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,aAAa,GACb,eAAe,GACf,gBAAgB,CAAC;AAerB,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B,GAAG,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;AAC1C,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,OAAuB,EACvB,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CAUP"} \ No newline at end of file diff --git a/dist/components/textbadge/TextBadge.component.js b/dist/components/textbadge/TextBadge.component.js new file mode 100644 index 0000000000..7313d793f4 --- /dev/null +++ b/dist/components/textbadge/TextBadge.component.js @@ -0,0 +1,18 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontWeight } from '../../style/theme'; +const StyledTextBadge = styled.span ` + ${({ theme, variant }) => ` + background-color: ${theme[variant]}; + color: ${variant === 'infoSecondary' ? theme.textPrimary : theme.textReverse}; + padding: 2px ${spacing.r4}; + border-radius: 4px; + font-size: 0.9rem; + font-weight: ${fontWeight.bold}; + margin: 0 ${spacing.r4} 0 ${spacing.r4}; + `} +`; +export function TextBadge({ text, variant = 'infoPrimary', className, ...rest }) { + return (_jsx(StyledTextBadge, { className: ['sc-text-badge', className].join(' '), variant: variant, ...rest, children: text })); +} diff --git a/dist/components/toast/DurationBasedProgressBar.d.ts b/dist/components/toast/DurationBasedProgressBar.d.ts new file mode 100644 index 0000000000..dcf95ecb42 --- /dev/null +++ b/dist/components/toast/DurationBasedProgressBar.d.ts @@ -0,0 +1,5 @@ +export declare function DurationBasedProgressBar({ duration, color, }: { + duration: number | null; + color: string; +}): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=DurationBasedProgressBar.d.ts.map \ No newline at end of file diff --git a/dist/components/toast/DurationBasedProgressBar.d.ts.map b/dist/components/toast/DurationBasedProgressBar.d.ts.map new file mode 100644 index 0000000000..8d3694c981 --- /dev/null +++ b/dist/components/toast/DurationBasedProgressBar.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DurationBasedProgressBar.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toast/DurationBasedProgressBar.tsx"],"names":[],"mappings":"AAIA,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf,2CAkCA"} \ No newline at end of file diff --git a/dist/components/toast/DurationBasedProgressBar.js b/dist/components/toast/DurationBasedProgressBar.js new file mode 100644 index 0000000000..a5b4fef038 --- /dev/null +++ b/dist/components/toast/DurationBasedProgressBar.js @@ -0,0 +1,24 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { darken } from 'polished'; +import { useEffect, useState } from 'react'; +import { ProgressBar } from '../progressbar/ProgressBar.component'; +export function DurationBasedProgressBar({ duration, color, }) { + const [progress, setProgress] = useState(0); + useEffect(() => { + if (duration) { + const interval = setInterval(() => { + setProgress((prevProgress) => prevProgress + (100 / duration) * 1000); + }, 1000); + return () => { + clearInterval(interval); + }; + } + }, [duration]); + return (_jsx("div", { style: { + position: 'absolute', + bottom: 0, + left: 0, + width: '100%', + borderRadius: 4, + }, children: _jsx(ProgressBar, { size: "custom", percentage: progress, color: color, backgroundColor: `${darken(0.1, color)}`, height: '4px' }) })); +} diff --git a/dist/components/toast/Toast.component.d.ts b/dist/components/toast/Toast.component.d.ts new file mode 100644 index 0000000000..082dbfde4c --- /dev/null +++ b/dist/components/toast/Toast.component.d.ts @@ -0,0 +1,20 @@ +import React, { ReactNode } from 'react'; +import { ToastPosition } from './ToastPositionHelpers'; +export type ToastStatus = 'success' | 'error' | 'warning' | 'info'; +export type ToastProps = { + open: boolean; + message: ReactNode; + onClose: () => void; + status?: ToastStatus; + position?: ToastPosition; + autoDismiss?: boolean; + duration?: number; + icon?: React.ReactNode; + width?: React.CSSProperties['width']; + withProgressBar?: boolean; + style?: React.CSSProperties; +}; +export declare const useGetBackgroundColor: (status: string) => string; +declare function Toast({ open, message, onClose, position, status, autoDismiss, duration, icon, width, withProgressBar, style, }: ToastProps): import("react/jsx-runtime").JSX.Element | null; +export { Toast }; +//# sourceMappingURL=Toast.component.d.ts.map \ No newline at end of file diff --git a/dist/components/toast/Toast.component.d.ts.map b/dist/components/toast/Toast.component.d.ts.map new file mode 100644 index 0000000000..40bbc661f1 --- /dev/null +++ b/dist/components/toast/Toast.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Toast.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toast/Toast.component.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAU,MAAM,OAAO,CAAC;AAMjD,OAAO,EAAE,aAAa,EAAkB,MAAM,wBAAwB,CAAC;AAKvE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,SAAS,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,MAAM,WAYnD,CAAC;AA6DF,iBAAS,KAAK,CAAC,EACb,IAAI,EACJ,OAAO,EACP,OAAO,EACP,QAAsB,EACtB,MAAe,EACf,WAAkB,EAClB,QAAe,EACf,IAAsC,EACtC,KAAqB,EACrB,eAAuB,EACvB,KAAK,GACN,EAAE,UAAU,kDAmEZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/toast/Toast.component.js b/dist/components/toast/Toast.component.js new file mode 100644 index 0000000000..519642feaa --- /dev/null +++ b/dist/components/toast/Toast.component.js @@ -0,0 +1,106 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { motion } from 'framer-motion'; +import { useRef } from 'react'; +import { useTheme } from 'styled-components'; +import { Box } from '../box/Box'; +import { Button } from '../buttonv2/Buttonv2.component'; +import { Icon } from '../icon/Icon.component'; +import { BasicText } from '../text/Text.component'; +import { positionOutput } from './ToastPositionHelpers'; +import { DurationBasedProgressBar } from './DurationBasedProgressBar'; +import { useToastParameters } from './useToastParameters'; +import styled from 'styled-components'; +export const useGetBackgroundColor = (status) => { + const theme = useTheme(); + switch (status) { + case 'success': + return theme.statusHealthy; + case 'error': + return theme.statusCritical; + case 'warning': + return theme.statusWarning; + default: + return theme.infoPrimary; + } +}; +const useGetRgbBackgroundColor = (status) => { + const theme = useTheme(); + switch (status) { + case 'success': + return `rgba(${theme.statusHealthyRGB}, 0.4)`; + case 'error': + return `rgba(${theme.statusCriticalRGB}, 0.4)`; + case 'warning': + return `rgba(${theme.statusWarningRGB}, 0.4)`; + default: + return theme.infoSecondary; + } +}; +const defaultIconName = (status) => { + switch (status) { + case 'success': + return 'Check-circle'; + case 'error': + return 'Times-circle'; + case 'warning': + return 'Exclamation-circle'; + default: + return 'Info-circle'; + } +}; +const DefaultIcon = ({ status }) => { + const color = useGetBackgroundColor(status); + const iconName = defaultIconName(status); + return _jsx(Icon, { name: iconName, color: color }); +}; +const DEFAULT_WIDTH = '25rem'; +const IconContainer = styled.div ` + align-items: center; + align-self: stretch; + border-radius: 4px 0px 0px 4px; + display: flex; + gap: 16px; + justify-content: center; + position: relative; + width: 32px; + background-color: ${(props) => props.bgColor}; +`; +const ContentContainer = styled.div ` + align-items: center; + align-self: stretch; + display: flex; + flex: 1; + flex-grow: 1; + gap: 8px; + padding: 0px 16px; + position: relative; +`; +function Toast({ open, message, onClose, position = 'top-right', status = 'info', autoDismiss = true, duration = 5000, icon = _jsx(DefaultIcon, { status: status }), width = DEFAULT_WIDTH, withProgressBar = false, style, }) { + const ref = useRef(null); + const { params } = useToastParameters({ + open, + duration: autoDismiss ? duration : null, + onClose, + }); + const positionStyle = positionOutput[position]; + const bgColor = useGetBackgroundColor(status); + const rgbBgColor = useGetRgbBackgroundColor(status); + const theme = useTheme(); + if (!open) { + return null; + } + return (_jsxs("div", { ref: ref, role: "status", "aria-live": "polite", "aria-labelledby": `${status}_toast`, style: { + position: 'fixed', + ...(style || positionStyle), + width, + }, children: [_jsxs(motion.div, { initial: { opacity: 0, y: -20 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 20 }, transition: { duration: 0.3 }, style: { + alignItems: 'flex-end', + backgroundColor: theme.backgroundLevel1, + border: `1px solid ${theme.border}`, + boxShadow: '0px 4px 10px 4px #000', + display: 'flex', + borderRadius: '4px', + position: 'relative', + }, children: [_jsx(IconContainer, { bgColor: rgbBgColor, children: icon }), _jsx(ContentContainer, { children: _jsx(BasicText, { children: message }) }), _jsx(Box, { display: "flex", alignItems: "center", alignSelf: "stretch", children: _jsx(Button, { icon: _jsx(Icon, { name: "Close", size: "lg", color: "textSecondary" }), onClick: params === null || params === void 0 ? void 0 : params.onClose, "aria-label": "Close", tooltip: { overlay: 'Close', placement: 'top' } }) })] }, "toast"), withProgressBar && (_jsx(DurationBasedProgressBar, { duration: autoDismiss ? duration : null, color: bgColor }))] })); +} +export { Toast }; diff --git a/dist/components/toast/ToastPositionHelpers.d.ts b/dist/components/toast/ToastPositionHelpers.d.ts new file mode 100644 index 0000000000..d7bcd59e16 --- /dev/null +++ b/dist/components/toast/ToastPositionHelpers.d.ts @@ -0,0 +1,4 @@ +import { CSSProperties } from 'react'; +export type ToastPosition = 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center'; +export declare const positionOutput: Record; +//# sourceMappingURL=ToastPositionHelpers.d.ts.map \ No newline at end of file diff --git a/dist/components/toast/ToastPositionHelpers.d.ts.map b/dist/components/toast/ToastPositionHelpers.d.ts.map new file mode 100644 index 0000000000..dc49355134 --- /dev/null +++ b/dist/components/toast/ToastPositionHelpers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ToastPositionHelpers.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toast/ToastPositionHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,WAAW,GACX,YAAY,GACZ,aAAa,GACb,cAAc,GACd,eAAe,CAAC;AAEpB,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,EAAE,aAAa,CA2B/D,CAAC"} \ No newline at end of file diff --git a/dist/components/toast/ToastPositionHelpers.js b/dist/components/toast/ToastPositionHelpers.js new file mode 100644 index 0000000000..81578c8a96 --- /dev/null +++ b/dist/components/toast/ToastPositionHelpers.js @@ -0,0 +1,28 @@ +export const positionOutput = { + 'top-left': { + top: '3rem', + left: '1rem', + }, + 'top-right': { + top: '3rem', + right: '1rem', + }, + 'top-center': { + top: '1rem', + left: '50%', + transform: 'translateX(-50%)', + }, + 'bottom-left': { + bottom: '1rem', + left: '1rem', + }, + 'bottom-right': { + bottom: '1rem', + right: '1rem', + }, + 'bottom-center': { + bottom: '1rem', + left: '50%', + transform: 'translateX(-50%)', + }, +}; diff --git a/dist/components/toast/ToastProvider.d.ts b/dist/components/toast/ToastProvider.d.ts new file mode 100644 index 0000000000..a6645d5f25 --- /dev/null +++ b/dist/components/toast/ToastProvider.d.ts @@ -0,0 +1,14 @@ +import { ReactNode } from 'react'; +import { ToastProps } from './Toast.component'; +export type ToastContextState = Omit; +export interface ToastContextType { + showToast: (toastProps: ToastContextState) => void; +} +export declare const ToastContext: import("react").Context; +interface ToastProviderProps { + children: ReactNode; +} +export declare const ToastProvider: React.FC>; +export declare const useToast: () => ToastContextType; +export {}; +//# sourceMappingURL=ToastProvider.d.ts.map \ No newline at end of file diff --git a/dist/components/toast/ToastProvider.d.ts.map b/dist/components/toast/ToastProvider.d.ts.map new file mode 100644 index 0000000000..4185f43574 --- /dev/null +++ b/dist/components/toast/ToastProvider.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ToastProvider.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toast/ToastProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuC,MAAM,OAAO,CAAC;AACvE,OAAO,EAAS,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACpD;AAED,eAAO,MAAM,YAAY,uDAExB,CAAC;AAEF,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB;AACD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAe/E,CAAC;AAEF,eAAO,MAAM,QAAQ,wBAMpB,CAAC"} \ No newline at end of file diff --git a/dist/components/toast/ToastProvider.js b/dist/components/toast/ToastProvider.js new file mode 100644 index 0000000000..f48ba1760a --- /dev/null +++ b/dist/components/toast/ToastProvider.js @@ -0,0 +1,18 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { createContext, useContext, useState } from 'react'; +import { Toast } from './Toast.component'; +export const ToastContext = createContext(undefined); +export const ToastProvider = ({ children }) => { + const [toastProps, setToastProps] = useState(null); + const showToast = (toastProps) => { + setToastProps(toastProps); + }; + return (_jsxs(ToastContext.Provider, { value: { showToast }, children: [children, toastProps && (_jsx(Toast, { ...toastProps, onClose: () => setToastProps(null) }))] })); +}; +export const useToast = () => { + const context = useContext(ToastContext); + if (!context) { + throw new Error('useToast must be used within a ToastProvider'); + } + return context; +}; diff --git a/dist/components/toast/useMutationsHandler.d.ts b/dist/components/toast/useMutationsHandler.d.ts new file mode 100644 index 0000000000..dabcbece95 --- /dev/null +++ b/dist/components/toast/useMutationsHandler.d.ts @@ -0,0 +1,41 @@ +import { ReactNode } from 'react'; +import { UseMutationOptions, UseMutationResult } from 'react-query'; +import { ToastContextState } from './ToastProvider'; +export type MutationConfig = { + mutation: T; + name: string; +}; +declare type GetResults = T extends MutationConfig> ? MutationConfig> : T extends MinimalMutationResult ? MutationConfig> : MutationConfig>; +declare type GetDescriptionBuilder = T extends MutationConfig> ? DescriptionBuilder : T extends MutationConfig> ? DescriptionBuilder : T extends MinimalMutationResult ? DescriptionBuilder : never; +/** + * MutationResults reducer recursively maps type param to results + */ +declare type MutationsResults = T extends [] ? [] : T extends [infer Head, ...infer Tail] ? [GetResults, ...MutationsResults] : T extends [infer Head] ? [GetResults] : unknown[] extends T ? T : never; +declare enum DescriptionBuilderStatus { + Success = "success", + Error = "error", + Idle = "idle" +} +type DescriptionBuilder = { + error?: Error; + data?: Data; + status: DescriptionBuilderStatus; + name: string; +}; +declare type DescriptionBuilders = T extends [] ? [] : T extends [infer Head, ...infer Tail] ? [GetDescriptionBuilder, ...DescriptionBuilders] : T extends [infer Head] ? [GetDescriptionBuilder] : T extends UseMutationOptions[] ? DescriptionBuilder[] : DescriptionBuilder[]; +type Props = { + mainMutation: MutationConfig; + dependantMutations?: readonly [...MutationsResults] | MutationConfig>[]; + messageDescriptionBuilder: (mutations: T extends [] ? [GetDescriptionBuilder] : [GetDescriptionBuilder, ...DescriptionBuilders]) => ReactNode; + toastProps?: Pick; +} & ({ + onMainMutationSuccess?: () => void; + onAllMutationsSuccess?: never; +} | { + onAllMutationsSuccess?: () => void; + onMainMutationSuccess?: never; +}); +export type MinimalMutationResult = Pick, 'isError' | 'isIdle' | 'isSuccess' | 'isLoading' | 'error' | 'data'>; +export declare const useMutationsHandler: , T extends any[] | []>({ mainMutation, dependantMutations, messageDescriptionBuilder, toastProps, ...rest }: Props) => void; +export {}; +//# sourceMappingURL=useMutationsHandler.d.ts.map \ No newline at end of file diff --git a/dist/components/toast/useMutationsHandler.d.ts.map b/dist/components/toast/useMutationsHandler.d.ts.map new file mode 100644 index 0000000000..6d2fa90702 --- /dev/null +++ b/dist/components/toast/useMutationsHandler.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useMutationsHandler.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toast/useMutationsHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA0B,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAY,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,QAAQ,EAAE,CAAC,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,OAAO,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,cAAc,CACnD,qBAAqB,CAAC,MAAM,KAAK,EAAE,MAAM,MAAM,CAAC,CACjD,GACG,cAAc,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GACpD,CAAC,SAAS,qBAAqB,CAAC,MAAM,KAAK,EAAE,MAAM,MAAM,CAAC,GAC1D,cAAc,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GACpD,cAAc,CAAC,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5D,OAAO,MAAM,qBAAqB,CAAC,CAAC,IAAI,CAAC,SAAS,cAAc,CAC9D,qBAAqB,CAAC,MAAM,KAAK,EAAE,MAAM,MAAM,CAAC,CACjD,GACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,GACjC,CAAC,SAAS,cAAc,CAAC,kBAAkB,CAAC,MAAM,KAAK,EAAE,MAAM,MAAM,CAAC,CAAC,GACvE,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,GACjC,CAAC,SAAS,qBAAqB,CAAC,MAAM,KAAK,EAAE,MAAM,MAAM,CAAC,GAC1D,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,GACjC,KAAK,CAAC;AAEV;;GAEG;AACH,OAAO,MAAM,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,GAC7D,EAAE,GACF,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,GACrC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAC7C,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,GACtB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAClB,OAAO,EAAE,SAAS,CAAC,GACnB,CAAC,GACD,KAAK,CAAC;AAEV,aAAK,wBAAwB;IAC3B,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,IAAI,SAAS;CACd;AAED,KAAK,kBAAkB,CAAC,IAAI,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,IAAI;IACzD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,wBAAwB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,OAAO,MAAM,mBAAmB,CAAC,CAAC,SAAS,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,GAC5D,EAAE,GACF,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,GACrC,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,GAC3D,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,GACtB,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,GAC7B,CAAC,SAAS,kBAAkB,CAC1B,MAAM,eAAe,EACrB,MAAM,MAAM,EACZ,MAAM,KAAK,CACZ,EAAE,GACH,kBAAkB,CAChB,OAAO,SAAS,KAAK,GAAG,eAAe,GAAG,KAAK,EAC/C,MAAM,CACP,EAAE,GACH,kBAAkB,EAAE,CAAC;AAEzB,KAAK,KAAK,CAAC,gBAAgB,EAAE,CAAC,SAAS,GAAG,EAAE,IAAI;IAC9C,YAAY,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAC/C,kBAAkB,CAAC,EACf,SAAS,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,GACjC,cAAc,CAAC,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAC9D,yBAAyB,EAAE,CACzB,SAAS,EAAE,CAAC,SAAS,EAAE,GACnB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC,GACzC,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,EAAE,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,KACrE,SAAS,CAAC;IACf,UAAU,CAAC,EAAE,IAAI,CACf,iBAAiB,EACjB,OAAO,GAAG,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,iBAAiB,CACtE,CAAC;CACH,GAAG,CACA;IAAE,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,qBAAqB,CAAC,EAAE,KAAK,CAAA;CAAE,GACrE;IAAE,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,qBAAqB,CAAC,EAAE,KAAK,CAAA;CAAE,CACxE,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,KAAK,EAAE,MAAM,IAAI,IAAI,CACrD,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAClD,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CACpE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,gBAAgB,SAAS,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,EAChE,CAAC,SAAS,GAAG,EAAE,GAAG,EAAE,wFAOnB,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,SA2E5B,CAAC"} \ No newline at end of file diff --git a/dist/components/toast/useMutationsHandler.js b/dist/components/toast/useMutationsHandler.js new file mode 100644 index 0000000000..52a4d6d752 --- /dev/null +++ b/dist/components/toast/useMutationsHandler.js @@ -0,0 +1,73 @@ +import { useCallback, useEffect } from 'react'; +import { useToast } from './ToastProvider'; +var DescriptionBuilderStatus; +(function (DescriptionBuilderStatus) { + DescriptionBuilderStatus["Success"] = "success"; + DescriptionBuilderStatus["Error"] = "error"; + DescriptionBuilderStatus["Idle"] = "idle"; +})(DescriptionBuilderStatus || (DescriptionBuilderStatus = {})); +export const useMutationsHandler = ({ mainMutation, dependantMutations, messageDescriptionBuilder, toastProps, ...rest }) => { + const { showToast } = useToast(); + const mutations = [ + mainMutation, + ...(dependantMutations ? dependantMutations : []), + ]; + const handleMutationsCompletion = useCallback(async () => { + var _a, _b, _c, _d, _e, _f, _g; + const results = await Promise.all(mutations.map((m) => m.mutation)); + const loadingMutations = mutations.filter((_, index) => results[index].isLoading); + const successMutations = mutations.filter((_, index) => results[index].isSuccess); + const errorMutations = mutations.filter((_, index) => results[index].isError); + const mainMutationDesc = { + data: (_a = mainMutation.mutation) === null || _a === void 0 ? void 0 : _a.data, + status: ((_b = mainMutation.mutation) === null || _b === void 0 ? void 0 : _b.isSuccess) + ? DescriptionBuilderStatus.Success + : ((_c = mainMutation.mutation) === null || _c === void 0 ? void 0 : _c.isIdle) + ? DescriptionBuilderStatus.Idle + : DescriptionBuilderStatus.Error, + name: mainMutation.name, + }; + const descriptionBuilders = [ + mainMutationDesc, + ...((dependantMutations === null || dependantMutations === void 0 ? void 0 : dependantMutations.map(({ mutation, name }) => ({ + data: mutation.data, + error: mutation.isError ? mutation.error : null, + status: mutation.isSuccess + ? DescriptionBuilderStatus.Success + : mutation.isIdle + ? DescriptionBuilderStatus.Idle + : DescriptionBuilderStatus.Error, + name, + }))) || []), + ]; + if (loadingMutations.length === 0) { + if (errorMutations.length > 0) { + if ((_d = mainMutation.mutation) === null || _d === void 0 ? void 0 : _d.isSuccess) { + 'onMainMutationSuccess' in rest && ((_e = rest === null || rest === void 0 ? void 0 : rest.onMainMutationSuccess) === null || _e === void 0 ? void 0 : _e.call(rest)); + } + showToast({ + open: true, + status: 'error', + message: messageDescriptionBuilder(descriptionBuilders), + ...toastProps, + }); + return; + } + else if (successMutations.length > 0) { + 'onMainMutationSuccess' in rest && ((_f = rest === null || rest === void 0 ? void 0 : rest.onMainMutationSuccess) === null || _f === void 0 ? void 0 : _f.call(rest)); + if (successMutations.length === mutations.length) { + 'onAllMutationsSuccess' in rest && ((_g = rest === null || rest === void 0 ? void 0 : rest.onAllMutationsSuccess) === null || _g === void 0 ? void 0 : _g.call(rest)); + } + showToast({ + open: true, + status: 'success', + message: messageDescriptionBuilder(descriptionBuilders), + ...(toastProps ? toastProps : {}), + }); + } + } + }, [JSON.stringify(mutations)]); + useEffect(() => { + handleMutationsCompletion(); + }, [handleMutationsCompletion]); +}; diff --git a/dist/components/toast/useToastParameters.d.ts b/dist/components/toast/useToastParameters.d.ts new file mode 100644 index 0000000000..e9bab29998 --- /dev/null +++ b/dist/components/toast/useToastParameters.d.ts @@ -0,0 +1,10 @@ +interface ToastParameters { + duration?: number | null; + open?: boolean; + onClose?: () => void; +} +export declare function useToastParameters(params: ToastParameters): { + params: ToastParameters; +}; +export {}; +//# sourceMappingURL=useToastParameters.d.ts.map \ No newline at end of file diff --git a/dist/components/toast/useToastParameters.d.ts.map b/dist/components/toast/useToastParameters.d.ts.map new file mode 100644 index 0000000000..25eb34d321 --- /dev/null +++ b/dist/components/toast/useToastParameters.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"useToastParameters.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toast/useToastParameters.ts"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe;;EAkDzD"} \ No newline at end of file diff --git a/dist/components/toast/useToastParameters.js b/dist/components/toast/useToastParameters.js new file mode 100644 index 0000000000..0005f54cc3 --- /dev/null +++ b/dist/components/toast/useToastParameters.js @@ -0,0 +1,39 @@ +import { useCallback, useEffect, useRef } from 'react'; +export function useToastParameters(params) { + const { duration = null, open, onClose } = params; + const timerAutoHide = useRef(); + useEffect(() => { + if (!open) { + return undefined; + } + function handleKeyDown(nativeEvent) { + if (!nativeEvent.defaultPrevented) { + if (nativeEvent.key === 'Escape' || nativeEvent.key === 'Esc') { + onClose === null || onClose === void 0 ? void 0 : onClose(); + } + } + } + document.addEventListener('keydown', handleKeyDown); + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [open, onClose]); + const setAutoHideTimer = useCallback((autoHideDurationParam) => { + if (!onClose || autoHideDurationParam == null) { + return; + } + clearTimeout(timerAutoHide.current); + timerAutoHide.current = setTimeout(() => { + onClose === null || onClose === void 0 ? void 0 : onClose(); + }, autoHideDurationParam); + }, [onClose]); + useEffect(() => { + if (open) { + setAutoHideTimer(duration); + } + return () => { + clearTimeout(timerAutoHide.current); + }; + }, [open, duration, setAutoHideTimer]); + return { params }; +} diff --git a/dist/components/toggle/Toggle.component.d.ts b/dist/components/toggle/Toggle.component.d.ts new file mode 100644 index 0000000000..37abd71271 --- /dev/null +++ b/dist/components/toggle/Toggle.component.d.ts @@ -0,0 +1,11 @@ +import { ChangeEvent, InputHTMLAttributes } from 'react'; +export type Props = InputHTMLAttributes & { + toggle: boolean; + onChange: (e: ChangeEvent) => void; + label?: string; + disabled?: boolean; +}; +declare function ToggleSwitch({ toggle, label, onChange, disabled, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export declare const Toggle: typeof ToggleSwitch; +export {}; +//# sourceMappingURL=Toggle.component.d.ts.map \ No newline at end of file diff --git a/dist/components/toggle/Toggle.component.d.ts.map b/dist/components/toggle/Toggle.component.d.ts.map new file mode 100644 index 0000000000..c25e2f1320 --- /dev/null +++ b/dist/components/toggle/Toggle.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Toggle.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/toggle/Toggle.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAU,MAAM,OAAO,CAAC;AAOjE,MAAM,MAAM,KAAK,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,GAAG;IAC1D,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA2DF,iBAAS,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAmD1E;AAED,eAAO,MAAM,MAAM,qBAAe,CAAC"} \ No newline at end of file diff --git a/dist/components/toggle/Toggle.component.js b/dist/components/toggle/Toggle.component.js new file mode 100644 index 0000000000..acc6e1adca --- /dev/null +++ b/dist/components/toggle/Toggle.component.js @@ -0,0 +1,77 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { useRef } from 'react'; +import styled, { css } from 'styled-components'; +import { LABEL_PREFIX, useFieldContext } from '../form/Form.component'; +import { Stack, spacing } from '../../spacing'; +import { Text } from '../text/Text.component'; +const ToggleContainer = styled.span ` + display: inline-flex; + align-items: center; + position: relative; + opacity: ${(props) => (props.disabled ? 0.5 : 1)}; +`; +const Switch = styled.label ` + position: relative; + width: ${spacing.r24}; + align-self: center; + ${(props) => { + return css ` + ${props.disabled + ? ` + cursor: not-allowed; + ` + : ` + cursor: pointer; + `} + `; +}} +`; +const Slider = styled.div ` + width: 100%; + height: 1rem; + background-color: ${(props) => props.theme.backgroundLevel1}; + border: ${spacing.r1} solid + ${(props) => props.theme[props.toggle ? 'selectedActive' : 'infoPrimary']}; + border-radius: ${spacing.r8}; + transition: 0.4s; + + &:before { + border-radius: 100%; + position: absolute; + content: ''; + height: ${spacing.r10}; + width: ${spacing.r10}; + left: 3px; + top: 3.5px; + background-color: ${(props) => props.theme[props.toggle ? 'textSecondary' : 'textPrimary']}; + transition: 0.4s; + } +`; +const ToggleInput = styled.input ` + &:checked + ${Slider} { + background-color: ${(props) => props.theme.selectedActive}; + } + &:checked + ${Slider}:before { + transform: translateX(${spacing.r10}); + } + display: none; +`; +const StyledSwitchLabel = styled.label ` + color: ${(props) => props.theme[props.toggle ? 'textPrimary' : 'textPrimary']}; +`; +function ToggleSwitch({ toggle, label, onChange, disabled, ...rest }) { + const { isContextAvailable } = useFieldContext(); + const checkboxRef = useRef(null); + return (_jsx(StyledSwitchLabel, { toggle: toggle, className: "text", id: `${rest['id']}-label`, htmlFor: rest['id'], children: _jsx(ToggleContainer, { className: "sc-toggle", disabled: disabled, children: _jsxs(Stack, { gap: 'r8', style: { alignItems: 'baseline' }, children: [_jsxs(Switch, { htmlFor: rest['id'], role: "checkbox", "aria-checked": toggle, tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, disabled: disabled, onKeyDown: (e) => { + if (e.code === 'Space' || e.code === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + checkboxRef.current && checkboxRef.current.click(); + } + }, "aria-labelledby": label + ? `${rest['id']}-label` + : isContextAvailable + ? `${LABEL_PREFIX}${rest['id']}` + : undefined, children: [_jsx(ToggleInput, { type: "checkbox", checked: toggle, onChange: onChange, disabled: disabled, ref: checkboxRef, ...rest }), _jsx(Slider, { className: "sc-slider", toggle: toggle })] }), label && _jsx(Text, { children: label })] }) }) })); +} +export const Toggle = ToggleSwitch; diff --git a/dist/components/tooltip/Tooltip.component.d.ts b/dist/components/tooltip/Tooltip.component.d.ts new file mode 100644 index 0000000000..ba06efe850 --- /dev/null +++ b/dist/components/tooltip/Tooltip.component.d.ts @@ -0,0 +1,23 @@ +import { CSSProperties } from 'react'; +export declare const TOP = "top"; +export declare const BOTTOM = "bottom"; +export declare const LEFT = "left"; +export declare const TOPSTART = "top-start"; +export declare const TOPEND = "top-end"; +export declare const RIGHT = "right"; +export declare const RIGHTSTART = "right-start"; +export declare const RIGHTEND = "right-end"; +export declare const BOTTOMEND = "bottom-end"; +export declare const BOTTOMSTART = "bottom-start"; +export declare const LEFTSTART = "left-start"; +export declare const LEFTEND = "left-end"; +export type Position = typeof TOP | typeof BOTTOM | typeof LEFT | typeof RIGHT | typeof TOPSTART | typeof TOPEND | typeof RIGHTSTART | typeof RIGHTEND | typeof BOTTOMEND | typeof BOTTOMSTART | typeof LEFTEND | typeof LEFTSTART; +export type Props = { + placement?: Position; + overlayStyle?: CSSProperties; + overlay?: React.ReactNode; + children?: React.ReactNode; +}; +declare function Tooltip({ placement, overlayStyle, children, overlay, ...rest }: Props): import("react/jsx-runtime").JSX.Element; +export { Tooltip }; +//# sourceMappingURL=Tooltip.component.d.ts.map \ No newline at end of file diff --git a/dist/components/tooltip/Tooltip.component.d.ts.map b/dist/components/tooltip/Tooltip.component.d.ts.map new file mode 100644 index 0000000000..62163b21c2 --- /dev/null +++ b/dist/components/tooltip/Tooltip.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Tooltip.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tooltip/Tooltip.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAA+B,MAAM,OAAO,CAAC;AAKnE,eAAO,MAAM,GAAG,QAAQ,CAAC;AACzB,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,eAAO,MAAM,IAAI,SAAS,CAAC;AAC3B,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,KAAK,UAAU,CAAC;AAC7B,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC,eAAO,MAAM,OAAO,aAAa,CAAC;AAClC,MAAM,MAAM,QAAQ,GAChB,OAAO,GAAG,GACV,OAAO,MAAM,GACb,OAAO,IAAI,GACX,OAAO,KAAK,GACZ,OAAO,QAAQ,GACf,OAAO,MAAM,GACb,OAAO,UAAU,GACjB,OAAO,QAAQ,GACf,OAAO,SAAS,GAChB,OAAO,WAAW,GAClB,OAAO,OAAO,GACd,OAAO,SAAS,CAAC;AACrB,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AA4CF,iBAAS,OAAO,CAAC,EACf,SAAe,EACf,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,GAAG,IAAI,EACR,EAAE,KAAK,2CA+CP;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/tooltip/Tooltip.component.js b/dist/components/tooltip/Tooltip.component.js new file mode 100644 index 0000000000..8fe85170db --- /dev/null +++ b/dist/components/tooltip/Tooltip.component.js @@ -0,0 +1,82 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +import { computePosition, flip, offset, shift } from '@floating-ui/dom'; +import { useEffect, useRef, useState } from 'react'; +import styled from 'styled-components'; +import { spacing } from '../../spacing'; +import { fontSize, zIndex } from '../../style/theme'; +import { getThemePropSelector } from '../../utils'; +export const TOP = 'top'; +export const BOTTOM = 'bottom'; +export const LEFT = 'left'; +export const TOPSTART = 'top-start'; +export const TOPEND = 'top-end'; +export const RIGHT = 'right'; +export const RIGHTSTART = 'right-start'; +export const RIGHTEND = 'right-end'; +export const BOTTOMEND = 'bottom-end'; +export const BOTTOMSTART = 'bottom-start'; +export const LEFTSTART = 'left-start'; +export const LEFTEND = 'left-end'; +const TooltipContainer = styled.div ` + position: relative; + display: inline-block; +`; +const TooltipOverLayContainer = styled.div ` + display: inline-block; + opacity: 0; + position: fixed; + width: max-content; + border: 1px solid ${getThemePropSelector('border')}; + background-color: ${(props) => (props && props.style && props.style.backgroundColor) || + props.theme.backgroundLevel1}; + color: ${(props) => (props && props.style && props.style.color) || props.theme.textPrimary}; + z-index: ${zIndex.tooltip}; + border-radius: 4px; + font-size: ${(props) => (props && props.style && props.style.fontSize) || fontSize.small}; + vertical-align: middle; + padding: ${spacing.r4} ${spacing.r8}; + max-width: 40rem; +`; +const TooltipText = styled.div ` + width: 100%; + ul, + ol { + padding-inline-start: ${spacing.r16}; + margin-block-start: 0; + margin-block-end: 0; + } + li { + margin-bottom: ${spacing.r8}; + } + li:last-child { + margin-bottom: 0; + } +`; +function Tooltip({ placement = TOP, overlayStyle, children, overlay, ...rest }) { + const childrenRef = useRef(null); + const tooltipRef = useRef(null); + const [isTooltipVisible, setIsTooltipVisible] = useState(false); + useEffect(() => { + if (childrenRef.current && tooltipRef.current) { + computePosition(childrenRef.current, tooltipRef.current, { + placement, + middleware: [offset(5), shift(), flip()], + }).then(({ x, y }) => { + if (tooltipRef.current) { + Object.assign(tooltipRef.current.style, { + opacity: '1', + // we set opacity to 1 to make sure the tooltip is not displayed before the position is computed + left: `${x}px`, + top: `${y}px`, + }); + } + }); + } + }, [tooltipRef.current, childrenRef.current, isTooltipVisible]); + return (_jsxs(TooltipContainer, { className: "sc-tooltip", onPointerEnter: () => { + setIsTooltipVisible(true); + }, onPointerLeave: () => { + setIsTooltipVisible(false); + }, children: [isTooltipVisible && overlay ? (_jsx(TooltipOverLayContainer, { ref: tooltipRef, className: "sc-tooltip-overlay", placement: placement, style: overlayStyle, children: _jsx(TooltipText, { className: "sc-tooltip-overlay-text", children: overlay }) })) : null, _jsx("div", { ref: childrenRef, children: children })] })); +} +export { Tooltip }; diff --git a/dist/components/vegachart/VegaChart.component.d.ts b/dist/components/vegachart/VegaChart.component.d.ts new file mode 100644 index 0000000000..387ccfdcad --- /dev/null +++ b/dist/components/vegachart/VegaChart.component.d.ts @@ -0,0 +1,13 @@ +export declare const TOP = "top"; +export declare const BOTTOM = "bottom"; +type Position = typeof TOP | typeof BOTTOM; +type Props = { + id: string; + spec: Record; + tooltipPosition?: Position; + theme?: 'light' | 'dark' | 'custom'; + className?: string; +}; +declare function VegaChart({ id, spec, tooltipPosition, theme, }: Props): import("react/jsx-runtime").JSX.Element; +export { VegaChart }; +//# sourceMappingURL=VegaChart.component.d.ts.map \ No newline at end of file diff --git a/dist/components/vegachart/VegaChart.component.d.ts.map b/dist/components/vegachart/VegaChart.component.d.ts.map new file mode 100644 index 0000000000..1deaff5247 --- /dev/null +++ b/dist/components/vegachart/VegaChart.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VegaChart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/vegachart/VegaChart.component.tsx"],"names":[],"mappings":"AAKA,eAAO,MAAM,GAAG,QAAQ,CAAC;AACzB,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,KAAK,QAAQ,GAAG,OAAO,GAAG,GAAG,OAAO,MAAM,CAAC;AAC3C,KAAK,KAAK,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA0BF,iBAAS,SAAS,CAAC,EACjB,EAAE,EACF,IAAI,EACJ,eAAwB,EACxB,KAAgB,GACjB,EAAE,KAAK,2CAkGP;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/components/vegachart/VegaChart.component.js b/dist/components/vegachart/VegaChart.component.js new file mode 100644 index 0000000000..e30008dd24 --- /dev/null +++ b/dist/components/vegachart/VegaChart.component.js @@ -0,0 +1,120 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +// @ts-nocheck +import { useEffect, useContext, useRef } from 'react'; +import vegaEmbed from 'vega-embed'; +import { ThemeContext, createGlobalStyle } from 'styled-components'; +import { getThemePropSelector } from '../../utils'; +export const TOP = 'top'; +export const BOTTOM = 'bottom'; +/* How to theme tooltip: +https://github.com/vega/vega-tooltip/blob/master/docs/customizing_your_tooltip.md +*/ +const VegaTooltipTheme = createGlobalStyle ` + #vg-tooltip-element.vg-tooltip.custom-theme { + padding: 8px; + position: fixed; + z-index: 1000; + font-family: 'Lato'; + font-size: 12px; + border-radius: 3px; + box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); + color: ${getThemePropSelector('textPrimary')}; + background-color: ${getThemePropSelector('backgroundLevel1')}; + border: 1px solid ${getThemePropSelector('border')}; + // customize the title + h2 { + color: ${getThemePropSelector('textSecondary')}; + margin-bottom: 10px; + font-size: 12px; + } + } +`; +function VegaChart({ id, spec, tooltipPosition = BOTTOM, theme = 'custom', }) { + const themeContext = useContext(ThemeContext); + const currentBackgroundColor = themeContext && themeContext.brand + ? themeContext.brand.backgroundLevel4 + : themeContext.backgroundLevel4; + // the background color of the view + const currentBackgroundColor2 = themeContext && themeContext.brand + ? themeContext.brand.backgroundLevel1 + : themeContext.backgroundLevel1; + const brandText = themeContext && themeContext.brand + ? themeContext.brand.textPrimary + : themeContext.textPrimary; + const themeConfig = { + config: { + background: currentBackgroundColor, + axis: { + labelColor: brandText, + titleColor: brandText, + grid: false, + domainColor: currentBackgroundColor2, + }, + title: { + color: brandText, + font: 'Lato', + }, + view: { + stroke: 'transparent', + fill: currentBackgroundColor2, + }, + // the headers provide a title and labels for faceted plots. + header: { + labelColor: brandText, + }, + // the label of max/min + text: { + color: brandText, + font: 'Lato', + }, + // the up, bottom trend line and verticle line when hover + rule: { + color: brandText, + }, + legend: { + labelColor: brandText, + titleColor: brandText, + }, + }, + }; + const themedSpec = { ...spec, ...themeConfig }; + const vegaInstance = useRef(); + let tooltipOptions = { + theme: theme, + }; + if (tooltipPosition === TOP) { + tooltipOptions = { + theme: theme, + offsetX: -85, + offsetY: -140, + }; + } + useEffect(() => { + let isMounted = true; + vegaEmbed(`#${id}`, themedSpec, { + renderer: 'svg', + // Override the DEFAULT_OPTIONS https://github.com/vega/vega-tooltip/blob/master/src/defaults.ts + tooltip: tooltipOptions, + /* Determines if action links + ("Export as PNG/SVG", "View Source", "View Vega" (only for Vega-Lite), "Open in Vega Editor") are included with the embedded view. + If the value is true, all action links will be shown and none if the value is false. */ + actions: false, + }) + .then((result) => { + vegaInstance.current = result; // result.view contains the Vega view + }) + .catch((...args) => { + if (isMounted) { + console.error(...args); // TODO: we should handle this with a retry or an error state of the component + } + }); + return () => { + isMounted = false; + if (vegaInstance.current) { + vegaInstance.current.view.finalize(); + } + }; + }, [id, themedSpec, tooltipOptions, vegaInstance]); + return (_jsx("div", { id: id, className: "sc-vegachart", children: _jsx(VegaTooltipTheme, {}) })); +} +export { VegaChart }; diff --git a/dist/components/vegachartv2/SyncedCursorCharts.d.ts b/dist/components/vegachartv2/SyncedCursorCharts.d.ts new file mode 100644 index 0000000000..0f4f913476 --- /dev/null +++ b/dist/components/vegachartv2/SyncedCursorCharts.d.ts @@ -0,0 +1,13 @@ +import React from 'react'; +export declare const SyncedCursorChartsContext: React.Context<{ + cursorX: number; + setCursorX: (cursorX: number) => void; +} | null>; +export declare const useCursorX: () => { + cursorX: number; + setCursorX: (cursorX: number) => void; +} | null; +export declare function SyncedCursorCharts({ children }: { + children: JSX.Element; +}): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=SyncedCursorCharts.d.ts.map \ No newline at end of file diff --git a/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map b/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map new file mode 100644 index 0000000000..bed3976147 --- /dev/null +++ b/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SyncedCursorCharts.d.ts","sourceRoot":"","sources":["../../../src/lib/components/vegachartv2/SyncedCursorCharts.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8C,MAAM,OAAO,CAAC;AACnE,eAAO,MAAM,yBAAyB;aAC3B,MAAM;gBACH,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;SACxB,CAAC;AAChB,eAAO,MAAM,UAAU,QAAO;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,GAAG,IAQH,CAAC;AACF,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,2CAYzE"} \ No newline at end of file diff --git a/dist/components/vegachartv2/SyncedCursorCharts.js b/dist/components/vegachartv2/SyncedCursorCharts.js new file mode 100644 index 0000000000..2d1456651f --- /dev/null +++ b/dist/components/vegachartv2/SyncedCursorCharts.js @@ -0,0 +1,17 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { useState, createContext, useContext } from 'react'; +export const SyncedCursorChartsContext = createContext(null); +export const useCursorX = () => { + const contextValue = useContext(SyncedCursorChartsContext); + if (contextValue === null) { + console.error("Can't use useCursorX() outside SyncedCursorCharts"); + } + return contextValue; +}; +export function SyncedCursorCharts({ children }) { + const [cursorX, setCursorX] = useState(0); + return (_jsx(SyncedCursorChartsContext.Provider, { value: { + cursorX, + setCursorX, + }, children: children })); +} diff --git a/dist/components/vegachartv2/VegaChartV2.component.d.ts b/dist/components/vegachartv2/VegaChartV2.component.d.ts new file mode 100644 index 0000000000..b52122ad86 --- /dev/null +++ b/dist/components/vegachartv2/VegaChartV2.component.d.ts @@ -0,0 +1,16 @@ +import React from 'react'; +import * as vega from 'vega'; +export declare const TOP = "top"; +export declare const BOTTOM = "bottom"; +type Position = typeof TOP | typeof BOTTOM; +type Props = { + spec: Record; + tooltipPosition?: Position; + theme?: 'light' | 'dark' | 'custom'; + id?: string; + onHover?: (dataPoint: any) => void; + formatTooltip?: (value: any, valueToHtml: (value: any) => string, maxDepth: number) => string; +}; +export declare const VegaChart: React.ForwardRefExoticComponent>; +export {}; +//# sourceMappingURL=VegaChartV2.component.d.ts.map \ No newline at end of file diff --git a/dist/components/vegachartv2/VegaChartV2.component.d.ts.map b/dist/components/vegachartv2/VegaChartV2.component.d.ts.map new file mode 100644 index 0000000000..77bb3f6c9f --- /dev/null +++ b/dist/components/vegachartv2/VegaChartV2.component.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"VegaChartV2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/vegachartv2/VegaChartV2.component.tsx"],"names":[],"mappings":"AACA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAC3E,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAK7B,eAAO,MAAM,GAAG,QAAQ,CAAC;AACzB,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,KAAK,QAAQ,GAAG,OAAO,GAAG,GAAG,OAAO,MAAM,CAAC;AAC3C,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,aAAa,CAAC,EAAE,CACd,KAAK,EAAE,GAAG,EACV,WAAW,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,EACnC,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC;CACb,CAAC;AA8PF,eAAO,MAAM,SAAS,gFAAsC,CAAC"} \ No newline at end of file diff --git a/dist/components/vegachartv2/VegaChartV2.component.js b/dist/components/vegachartv2/VegaChartV2.component.js new file mode 100644 index 0000000000..2d87c6b2ac --- /dev/null +++ b/dist/components/vegachartv2/VegaChartV2.component.js @@ -0,0 +1,218 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +// @ts-nocheck +import React, { useEffect, useRef, useLayoutEffect, useMemo } from 'react'; +import * as vega from 'vega'; +import vegaEmbed from 'vega-embed'; +import { createGlobalStyle, css, useTheme } from 'styled-components'; +import { useCursorX, SyncedCursorChartsContext } from './SyncedCursorCharts'; +import { TooltipHandlerWithPaint } from '../linetemporalchart/tooltip'; +export const TOP = 'top'; +export const BOTTOM = 'bottom'; +/* How to theme tooltip: +https://github.com/vega/vega-tooltip/blob/master/docs/customizing_your_tooltip.md +*/ +const VegaTooltipTheme = createGlobalStyle ` + #vg-tooltip-element.vg-tooltip.custom-theme { + ${(props) => { + const { theme } = props; + return css ` + padding: 8px; + position: fixed; + z-index: 1000; + width: calc(100vw / 6); + font-family: 'Lato'; + font-size: 12px; + border-radius: 3px; + box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); + color: ${theme.textPrimary}; + background-color: ${theme.backgroundLevel1}; + border: 1px solid ${theme.border}; + // customize the title + h2 { + color: ${theme.textPrimary}; + margin-bottom: 10px; + font-size: 12px; + } + table { + width: 100%; + } + table tr td.key { + color: ${theme.textSecondary}; + } + `; +}} + + } +`; +function VegaChartInternal({ spec, tooltipPosition = BOTTOM, theme = 'custom', formatTooltip, onHover, }, ref) { + // $FlowFixMe + const { cursorX, setCursorX } = useCursorX(); + const currentTheme = useTheme(); + const themeConfig = { + config: { + background: 'transparent', + axis: { + labelColor: currentTheme.textSecondary, + titleColor: currentTheme.textSecondary, + grid: false, + domainColor: 'transparent', + }, + title: { + color: currentTheme.textPrimary, + font: 'Lato', + }, + view: { + stroke: currentTheme.border, + strokeWidth: 0.5, + fill: currentTheme.backgroundLevel1, + }, + // the headers provide a title and labels for faceted plots. + header: { + labelColor: currentTheme.textPrimary, + }, + // the label of max/min + text: { + color: currentTheme.textPrimary, + font: 'Lato', + }, + legend: { + labelColor: currentTheme.textSecondary, + }, + }, + }; + const themedSpec = { ...spec, ...themeConfig }; + const vegaInstance = useRef(); + const vegaDOMInstance = useRef(null); + let tooltipOptions = { + theme: theme, + formatTooltip: formatTooltip, + }; + if (tooltipPosition === TOP) { + tooltipOptions = { + theme: theme, + offsetX: -85, + offsetY: -140, + formatTooltip: formatTooltip, + }; + } + const tooltipHandler = useMemo(() => new TooltipHandlerWithPaint(tooltipOptions, onHover), [theme]); + /* + useEffect() and useEffectLayout(): + The first effect will only render once, to initalize the chart and add the event lisener. + The second useEffectLayout is in charge of updating the chart when the `themedSpec` or `tooltipOptions` get updated. + Note it's important to useEffectLayout for the performance. + */ + useEffect(() => { + let isMounted = true; + // embed(el, spec[, opt]) the el can be a DOM element or CSS selector. https://github.com/vega/vega-embed + vegaDOMInstance && + vegaDOMInstance.current && + vegaEmbed(vegaDOMInstance.current, themedSpec, { + renderer: 'svg', + // Override the DEFAULT_OPTIONS https://github.com/vega/vega-tooltip/blob/master/src/defaults.ts + tooltip: tooltipHandler.call, + /* Determines if action links + ("Export as PNG/SVG", "View Source", "View Vega" (only for Vega-Lite), "Open in Vega Editor") are included with the embedded view. + If the value is true, all action links will be shown and none if the value is false. */ + actions: false, + }) + .then((result) => { + vegaInstance.current = result; + // result.view contains the Vega view + // get the current state of view: result.view.getState() + const view = result.view; + if (ref) { + ref.current = view; + } + if (SyncedCursorChartsContext && view) { + view.addEventListener('mouseover', function (event, item) { + const currentTime = item && + item.datum && + item.datum.datum && + item.datum.datum.timestamp; + if (currentTime) { + setCursorX(currentTime); + } + }); + /*When the mouse leaves the chart area, set the cursorX to null*/ + view.addEventListener('mouseleave', function (event, item) { + setCursorX(0); + }); + } + }) + .catch((...args) => { + if (isMounted) { + console.error(...args); // TODO: we should handle this with a retry or an error state of the component + } + }); + return () => { + isMounted = false; + if (vegaInstance.current) { + vegaInstance.current.view.finalize(); + } + }; // eslint-disable-next-line react-hooks/exhaustive-deps + }, [vegaDOMInstance, currentTheme]); + useLayoutEffect(() => { + if (vegaInstance.current) { + const view = vegaInstance.current.view; + tooltipHandler.options.formatTooltip = formatTooltip; + tooltipHandler.onHover = onHover; + view.tooltip(tooltipHandler.call).run(); + tooltipHandler.paint(); // to repaint the tooltip + } + }, [formatTooltip, vegaInstance, onHover]); + useLayoutEffect(() => { + if (vegaInstance.current) { + const view = vegaInstance.current.view; + let changeset = vega + .changeset() + .remove(() => true) + .insert(themedSpec.data.values); + //only the data.values changes trigger the graph's repaint + // For some reason source_0 is the default dataset name + view + .change('source_0', changeset) + .runAsync() + .then(() => { + // call resize() after the data is loaded to make sure the width is set correctly. + view.resize().runAsync(); + }); + } // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + // eslint-disable-next-line + JSON.stringify(themedSpec.data.values), + vegaInstance, + ]); + useLayoutEffect(() => { + if (vegaInstance.current && themedSpec.params) { + const view = vegaInstance.current.view; + // when the mouse go out, we trigger the event to set cursorX to null + if (!themedSpec.params.find((param) => param.name === 'cursorX').value || + !cursorX) { + view + .signal('cursorX', (themedSpec && + themedSpec.data && + themedSpec.data.values && + themedSpec.data.values[0] && + themedSpec.data.values[0].timestamp) || + Date.now()) + .run(); + view.signal('isCursorDisplayed', false).run(); + } + else { + view + .signal('cursorX', themedSpec.params.find((param) => param.name === 'cursorX').value) + .run(); + view.signal('isCursorDisplayed', true).run(); + } + } // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + // eslint-disable-next-line + JSON.stringify(themedSpec), + vegaInstance, + ]); + return (_jsx("div", { className: "sc-vegachart", ref: vegaDOMInstance, style: { + width: '100%', + }, children: _jsx(VegaTooltipTheme, {}) })); +} // @ts-expect-error +export const VegaChart = React.forwardRef(VegaChartInternal); diff --git a/dist/hooks.d.ts b/dist/hooks.d.ts new file mode 100644 index 0000000000..4cbfdc5fc0 --- /dev/null +++ b/dist/hooks.d.ts @@ -0,0 +1,2 @@ +export declare function useMemoCompare(next: T, compare: (previous: T | null, next: T) => boolean): T | null; +//# sourceMappingURL=hooks.d.ts.map \ No newline at end of file diff --git a/dist/hooks.d.ts.map b/dist/hooks.d.ts.map new file mode 100644 index 0000000000..7e6ec3528b --- /dev/null +++ b/dist/hooks.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/lib/hooks.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,CAAC,EAC9B,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,OAAO,YAqBlD"} \ No newline at end of file diff --git a/dist/hooks.js b/dist/hooks.js new file mode 100644 index 0000000000..e06c14a3e3 --- /dev/null +++ b/dist/hooks.js @@ -0,0 +1,19 @@ +import { useEffect, useRef } from 'react'; +export function useMemoCompare(next, compare) { + // Ref for storing previous value + const previousRef = useRef(null); + const previous = previousRef.current; + // Pass previous and next value to compare function + // to determine whether to consider them equal. + const isEqual = compare(previous, next); + // If not equal update previousRef to next value. + // We only update if not equal so that this hook continues to return + // the same old value if compare keeps returning true. + useEffect(() => { + if (!isEqual) { + previousRef.current = next; + } + }); + // Finally, if equal then return the previous value + return isEqual ? previous : next; +} diff --git a/dist/icons/branding-logo.d.ts b/dist/icons/branding-logo.d.ts new file mode 100644 index 0000000000..1bcc018f12 --- /dev/null +++ b/dist/icons/branding-logo.d.ts @@ -0,0 +1,3 @@ +declare const Logo: () => import("react/jsx-runtime").JSX.Element; +export { Logo }; +//# sourceMappingURL=branding-logo.d.ts.map \ No newline at end of file diff --git a/dist/icons/branding-logo.d.ts.map b/dist/icons/branding-logo.d.ts.map new file mode 100644 index 0000000000..791c38d650 --- /dev/null +++ b/dist/icons/branding-logo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"branding-logo.d.ts","sourceRoot":"","sources":["../../src/lib/icons/branding-logo.tsx"],"names":[],"mappings":"AAEA,QAAA,MAAM,IAAI,+CA0CT,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/icons/branding-logo.js b/dist/icons/branding-logo.js new file mode 100644 index 0000000000..76eca24e4d --- /dev/null +++ b/dist/icons/branding-logo.js @@ -0,0 +1,3 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +const Logo = () => (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "49", height: "49", viewBox: "0 0 49 49", children: [_jsx("path", { fill: "#3d9bd6", d: "M21.25 4.42v7.25h3.99V4.33l5.16 2.92 2-3.36L27.14.97A7.7 7.7 0 0 0 23.15 0c-1.36 0-2.72.35-3.89 1.06L14 3.98l1.99 3.36z" }), _jsx("path", { fill: "#007664", d: "M21.25 4.42v7.25h3.99V4.33l5.16 2.92 2-3.36L27.14.97A7.7 7.7 0 0 0 23.15 0c-1.36 0-2.72.35-3.89 1.06L14 3.98l1.99 3.36z" }), _jsx("path", { fill: "#ee4642", d: "M21.16 44.25V37h3.99v7.25l5.16-2.92 2 3.36-5.17 2.92a7.9 7.9 0 0 1-7.88 0L14 44.69l1.99-3.36z" }), _jsx("path", { fill: "#2aad8e", d: "M40.43 13.28L34 16.9l1.99 3.36 6.44-3.62v5.83h3.99v-5.92c0-1.33-.37-2.65-1.09-3.8a8.82 8.82 0 0 0-2.9-2.83L37.17 7l-1.99 3.36z" }), _jsx("path", { fill: "#d71d4f", d: "M4.99 32.84l6.43-3.63 2 3.36-6.44 3.63 5.17 2.91-2 3.36-5.25-2.92a7.6 7.6 0 0 1-2.81-2.82A7.1 7.1 0 0 1 1 32.92V27h3.99z" }), _jsx("path", { fill: "#9e2569", d: "M4.08 16.64l6.43 3.62 2-3.36-6.44-3.62 5.17-2.92-2-3.36-5.25 2.92a8.72 8.72 0 0 0-2.9 2.83A7.16 7.16 0 0 0 0 16.64v5.92h3.99z" }), _jsx("path", { fill: "#f79836", d: "M40.34 36.2L34 32.57l1.99-3.36 6.44 3.63V27h3.99v5.92c0 1.33-.37 2.57-1.09 3.81a8.69 8.69 0 0 1-2.9 2.82l-5.26 2.92-1.99-3.36z" }), _jsx("path", { fill: "#007664", d: "M24 15v8.22l7.34-4.06z" }), _jsx("path", { fill: "#9e2569", d: "M23.25 15L16 19.16l7.25 4.06z" }), _jsx("path", { fill: "#d71d4f", d: "M22.25 25.07L15 21v8.13z" }), _jsx("path", { fill: "#2aad8e", d: "M24 24.98l7.25 4.07V21z" }), _jsx("path", { fill: "#ee4642", d: "M23.16 26L16 30.07l7.16 4.15z" }), _jsx("path", { fill: "#f79836", d: "M24 26v8.22l7.25-4.15z" })] })); +export { Logo }; diff --git a/dist/icons/branding.d.ts b/dist/icons/branding.d.ts new file mode 100644 index 0000000000..b91c7425db --- /dev/null +++ b/dist/icons/branding.d.ts @@ -0,0 +1,3 @@ +declare const Logo: () => import("react/jsx-runtime").JSX.Element; +export { Logo }; +//# sourceMappingURL=branding.d.ts.map \ No newline at end of file diff --git a/dist/icons/branding.d.ts.map b/dist/icons/branding.d.ts.map new file mode 100644 index 0000000000..35c24e2776 --- /dev/null +++ b/dist/icons/branding.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../../src/lib/icons/branding.tsx"],"names":[],"mappings":"AAEA,QAAA,MAAM,IAAI,+CAkDT,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/icons/branding.js b/dist/icons/branding.js new file mode 100644 index 0000000000..5a98977f53 --- /dev/null +++ b/dist/icons/branding.js @@ -0,0 +1,3 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +const Logo = () => (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "186", height: "49", viewBox: "0 0 186 49", children: [_jsx("path", { fill: "#fff", d: "M72.23 18.19c0-2.03-1.18-3.18-4.53-3.18-3.35 0-4.53 1.15-4.53 3.18v.71c0 1.68 1.09 2.21 1.9 2.47l6.98 2.57c2.27.88 4.17 2.29 4.17 5.04v3.09c0 3.09-2.27 5.75-8.61 5.75-6.43 0-8.61-2.66-8.61-5.75v-2.03c0-.53.27-.71.82-.71h2.26c.45 0 .64.18.64.71v1.68c0 2.03 1.45 3.18 4.89 3.18 3.44 0 4.89-1.15 4.89-3.18v-1.77c0-1.86-1.72-2.48-3.17-3.1l-6.43-2.38a4.98 4.98 0 0 1-3.36-4.6v-2.12c0-3.1 2-5.75 8.16-5.75 6.25 0 8.25 2.65 8.25 5.75v1.68c0 .44-.18.7-.64.7h-2.26c-.55 0-.82-.17-.82-.7zM97.04 32.16c0 3.09-1.91 5.75-8.52 5.75-6.62 0-8.52-2.66-8.52-5.75V17.75c0-3.1 1.9-5.75 8.52-5.75 6.61 0 8.52 2.65 8.52 5.75v1.85c0 .53-.18.71-.73.71h-2.17c-.55 0-.82-.18-.82-.71v-1.23c0-2.04-1.36-3.28-4.8-3.28-3.44 0-4.8 1.24-4.8 3.28v13.26c0 2.03 1.36 3.27 4.8 3.27 3.44 0 4.8-1.24 4.8-3.27v-1.77c0-.44.27-.71.82-.71h2.17c.46 0 .73.27.73.71zM125.81 34.28h9.78c.46 0 .82.18.82.71v1.68c0 .53-.36.71-.82.71h-12.96c-.45 0-.63-.27-.63-.71V12.8c0-.53.18-.8.73-.8h2.35c.45 0 .73.27.73.8zM164.58 12c.46 0 .64.18.64.71v1.68c0 .53-.09.7-.64.7h-5.98v21.58c0 .53-.27.71-.81.71h-2.36c-.45 0-.81-.27-.81-.71V15.09h-5.99c-.54 0-.63-.17-.63-.7v-1.68c0-.53.09-.71.63-.71z" }), _jsx("path", { fill: "#fff", d: "M72.23 18.19c0-2.03-1.18-3.18-4.53-3.18-3.35 0-4.53 1.15-4.53 3.18v.71c0 1.68 1.09 2.21 1.9 2.47l6.98 2.57c2.27.88 4.17 2.29 4.17 5.04v3.09c0 3.09-2.27 5.75-8.61 5.75-6.43 0-8.61-2.66-8.61-5.75v-2.03c0-.53.27-.71.82-.71h2.26c.45 0 .64.18.64.71v1.68c0 2.03 1.45 3.18 4.89 3.18 3.44 0 4.89-1.15 4.89-3.18v-1.77c0-1.86-1.72-2.48-3.17-3.1l-6.43-2.38a4.98 4.98 0 0 1-3.36-4.6v-2.12c0-3.1 2-5.75 8.16-5.75 6.25 0 8.25 2.65 8.25 5.75v1.68c0 .44-.18.7-.64.7h-2.26c-.55 0-.82-.17-.82-.7zM97.04 32.16c0 3.09-1.91 5.75-8.52 5.75-6.62 0-8.52-2.66-8.52-5.75V17.75c0-3.1 1.9-5.75 8.52-5.75 6.61 0 8.52 2.65 8.52 5.75v1.85c0 .53-.18.71-.73.71h-2.17c-.55 0-.82-.18-.82-.71v-1.23c0-2.04-1.36-3.28-4.8-3.28-3.44 0-4.8 1.24-4.8 3.28v13.26c0 2.03 1.36 3.27 4.8 3.27 3.44 0 4.8-1.24 4.8-3.27v-1.77c0-.44.27-.71.82-.71h2.17c.46 0 .73.27.73.71zM125.81 34.28h9.78c.46 0 .82.18.82.71v1.68c0 .53-.36.71-.82.71h-12.96c-.45 0-.63-.27-.63-.71V12.8c0-.53.18-.8.73-.8h2.35c.45 0 .73.27.73.8zM143.72 36.67c0 .53-.19.71-.73.71h-2.36c-.45 0-.63-.27-.63-.71V12.8c0-.53.09-.8.63-.8h2.36c.54 0 .73.27.73.8zM164.58 12c.46 0 .64.18.64.71v1.68c0 .53-.09.7-.64.7h-5.98v21.58c0 .53-.27.71-.81.71h-2.36c-.45 0-.81-.27-.81-.71V15.09h-5.99c-.54 0-.63-.17-.63-.7v-1.68c0-.53.09-.71.63-.71zM175.53 23.76l5.71-11.05c.18-.36.36-.71.82-.71h2.35c.55 0 .82.27.55.71l-7.53 14.59v9.37c0 .44-.18.71-.72.71h-2.36c-.54 0-.63-.27-.63-.71V27.3l-7.61-14.59c-.28-.44 0-.71.54-.71h2.27c.54 0 .63.27.9.71zM110.76 12c.45 0 .73.27.91.71l7.43 23.96c.18.44 0 .71-.54.71h-2.45c-.45 0-.73-.27-.82-.71l-1.72-5.75h-7.97l-1.73 5.75c-.09.44-.36.71-.81.71h-2.45c-.54 0-.72-.27-.54-.71l7.43-23.96c.18-.44.45-.71.91-.71zm-1.18 5.48l-3.17 10.61h6.25z" }), _jsx("path", { fill: "#3d9bd6", d: "M21.25 4.42v7.25h3.99V4.33l5.16 2.92 2-3.36L27.14.97A7.7 7.7 0 0 0 23.15 0c-1.36 0-2.72.35-3.89 1.06L14 3.98l1.99 3.36z" }), _jsx("path", { fill: "#007664", d: "M21.25 4.42v7.25h3.99V4.33l5.16 2.92 2-3.36L27.14.97A7.7 7.7 0 0 0 23.15 0c-1.36 0-2.72.35-3.89 1.06L14 3.98l1.99 3.36z" }), _jsx("path", { fill: "#ee4642", d: "M21.16 44.25V37h3.99v7.25l5.16-2.92 2 3.36-5.17 2.92a7.9 7.9 0 0 1-7.88 0L14 44.69l1.99-3.36z" }), _jsx("path", { fill: "#2aad8e", d: "M40.43 13.28L34 16.9l1.99 3.36 6.44-3.62v5.83h3.99v-5.92c0-1.33-.37-2.65-1.09-3.8a8.82 8.82 0 0 0-2.9-2.83L37.17 7l-1.99 3.36z" }), _jsx("path", { fill: "#d71d4f", d: "M4.99 32.84l6.43-3.63 2 3.36-6.44 3.63 5.17 2.91-2 3.36-5.25-2.92a7.6 7.6 0 0 1-2.81-2.82A7.1 7.1 0 0 1 1 32.92V27h3.99z" }), _jsx("path", { fill: "#9e2569", d: "M4.08 16.64l6.43 3.62 2-3.36-6.44-3.62 5.17-2.92-2-3.36-5.25 2.92a8.72 8.72 0 0 0-2.9 2.83A7.16 7.16 0 0 0 0 16.64v5.92h3.99z" }), _jsx("path", { fill: "#f79836", d: "M40.34 36.2L34 32.57l1.99-3.36 6.44 3.63V27h3.99v5.92c0 1.33-.37 2.57-1.09 3.81a8.69 8.69 0 0 1-2.9 2.82l-5.26 2.92-1.99-3.36z" }), _jsx("path", { fill: "#007664", d: "M24 15v8.22l7.34-4.06z" }), _jsx("path", { fill: "#9e2569", d: "M23.25 15L16 19.16l7.25 4.06z" }), _jsx("path", { fill: "#d71d4f", d: "M22.25 25.07L15 21v8.13z" }), _jsx("path", { fill: "#2aad8e", d: "M24 24.98l7.25 4.07V21z" }), _jsx("path", { fill: "#ee4642", d: "M23.16 26L16 30.07l7.16 4.15z" }), _jsx("path", { fill: "#f79836", d: "M24 26v8.22l7.25-4.15z" })] })); +export { Logo }; diff --git a/dist/icons/scality-loading.d.ts b/dist/icons/scality-loading.d.ts new file mode 100644 index 0000000000..07bed6bf34 --- /dev/null +++ b/dist/icons/scality-loading.d.ts @@ -0,0 +1,3 @@ +declare const LoaderIcon: () => import("react/jsx-runtime").JSX.Element; +export { LoaderIcon }; +//# sourceMappingURL=scality-loading.d.ts.map \ No newline at end of file diff --git a/dist/icons/scality-loading.d.ts.map b/dist/icons/scality-loading.d.ts.map new file mode 100644 index 0000000000..b69c5258a6 --- /dev/null +++ b/dist/icons/scality-loading.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"scality-loading.d.ts","sourceRoot":"","sources":["../../src/lib/icons/scality-loading.tsx"],"names":[],"mappings":"AAEA,QAAA,MAAM,UAAU,+CAiHf,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/icons/scality-loading.js b/dist/icons/scality-loading.js new file mode 100644 index 0000000000..bbbaa8fb1f --- /dev/null +++ b/dist/icons/scality-loading.js @@ -0,0 +1,3 @@ +import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; +const LoaderIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", version: "1.1", viewBox: "0 0 56 56", width: "50", height: "50", children: _jsxs("g", { className: "container", children: [_jsx("path", { d: "M25.80000004768371,5.250000393390657 v8.2 H30.200000047683716 V5.1500003933906555 l5.7,3.3 l2.2,-3.8 l-5.8,-3.3 c-1.3,-0.8 -2.8,-1.1 -4.4,-1.1 c-1.5,0 -3,0.4 -4.3,1.2 l-5.8,3.3 l2.2,3.8 L25.80000004768371,5.250000393390657 z", className: "svg_3", children: _jsx("animate", { attributeName: "opacity", attributeType: "XML", values: "1; 0", begin: "0s", dur: "1s", repeatCount: "indefinite" }) }), _jsx("path", { d: "M46.60000004768372,14.650000393390656 l-7.1,4.1 l2.2,3.8 l7.1,-4.1 l0,6.6 l4.4,0 l0,-6.7 c0,-1.5 -0.4,-3 -1.2,-4.3 c-0.8,-1.3 -1.9,-2.4 -3.2,-3.2 l-5.8,-3.3 l-2.2,3.8 L46.60000004768372,14.650000393390656 z", className: "svg_5", children: _jsx("animate", { attributeName: "opacity", attributeType: "XML", values: "1; 0", begin: "0.3s", dur: "1s", repeatCount: "indefinite" }) }), _jsx("path", { d: "M46.60000004768372,41.25000039339065 L39.60000004768372,37.150000393390656 l2.2,-3.8 l7.1,4.1 l0,-6.6 l4.4,0 l0,6.7 c0,1.5 -0.4,2.9 -1.2,4.3 c-0.8,1.3 -1.9,2.4 -3.2,3.2 l-5.8,3.3 l-2.2,-3.8 L46.60000004768372,41.25000039339065 z", className: "svg_8", children: _jsx("animate", { attributeName: "opacity", attributeType: "XML", values: "1; 0", begin: "0.55s", dur: "1s", repeatCount: "indefinite" }) }), _jsx("path", { d: "M25.80000004768371,50.75000039339065 v-8.2 H30.200000047683716 v8.2 l5.7,-3.3 l2.2,3.8 l-5.7,3.3 c-1.3,0.8 -2.9,1.2 -4.4,1.2 c-1.5,0 -3,-0.4 -4.3,-1.2 l-5.8,-3.3 l2.2,-3.8 L25.80000004768371,50.75000039339065 z", className: "svg_4", children: _jsx("animate", { attributeName: "opacity", attributeType: "XML", values: "1; 0", begin: "0.75s", dur: "1s", repeatCount: "indefinite" }) }), _jsx("path", { d: "M7.2000000476837185,37.45000039339065 l7.1,-4.1 l2.2,3.8 l-7.1,4.1 l5.7,3.3 l-2.2,3.8 l-5.8,-3.3 c-1.3,-0.8 -2.4,-1.9 -3.1,-3.2 c-0.8,-1.3 -1.2,-2.8 -1.2,-4.3 l0,-6.7 l4.4,0 L7.2000000476837185,37.45000039339065 z", className: "svg_6", children: _jsx("animate", { attributeName: "opacity", attributeType: "XML", values: "1; 0", begin: "0.85s", dur: "1s", repeatCount: "indefinite" }) }), _jsx("path", { d: "M7.2000000476837185,18.550000393390654 l7.1,4.1 l2.2,-3.8 l-7.1,-4.1 l5.7,-3.3 l-2.2,-3.8 l-5.8,3.3 c-1.3,0.8 -2.4,1.9 -3.2,3.2 c-0.8,1.3 -1.2,2.8 -1.2,4.4 l0,6.7 l4.4,0 L7.2000000476837185,18.550000393390654 z", className: "svg_7", children: _jsx("animate", { attributeName: "opacity", attributeType: "XML", values: "1; 0", begin: "0.9", dur: "1s", repeatCount: "indefinite" }) }), _jsx("polygon", { points: "28.60000228881836,17.649999976158142 28.60000228881836,26.950003027915955 36.70000076293945,22.34999692440033 ", className: "svg_9" }), _jsx("polygon", { points: "27.39999771118164,17.649999976158142 19.39999771118164,22.34999692440033 27.39999771118164,26.950003027915955 ", className: "svg_10" }), _jsx("polygon", { points: "26.89999771118164,27.950003027915955 18.89999771118164,23.34999692440033 18.89999771118164,32.55000340938568 ", className: "svg_11" }), _jsx("polygon", { points: "29.200000762939453,27.950003027915955 37.20000076293945,32.55000340938568 37.20000076293945,23.450003027915955 ", className: "svg_12" }), _jsx("polygon", { points: "27.39999771118164,29.05000150203705 19.500003814697266,33.650001883506775 27.39999771118164,38.34999883174896 ", className: "svg_13" }), _jsx("polygon", { points: "28.60000228881836,29.05000150203705 28.60000228881836,38.34999883174896 36.60000228881836,33.650001883506775 ", className: "svg_14" })] }) })); +export { LoaderIcon }; diff --git a/dist/index.css b/dist/index.css new file mode 100644 index 0000000000..edeea0cba5 --- /dev/null +++ b/dist/index.css @@ -0,0 +1,25 @@ +html, +body { + font-family: 'Lato'; + font-size: max(14px, 0.972vw); +} + +/* Lato-Regular */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: normal; + src: local(''), url('./style/fonts/Lato-Regular.woff2') format('woff2'), + /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('./style/fonts/Lato-Regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* Lato-Bold */ +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: bold; + src: local(''), url('./style/fonts/Lato-Bold.woff2') format('woff2'), + /* Chrome 26+, Opera 23+, Firefox 39+ */ url('./style/fonts/Lato-Bold.woff') + format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000000..4af01473e2 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,64 @@ +export { Banner } from './components/banner/Banner.component'; +export { Breadcrumb } from './components/breadcrumb/Breadcrumb.component'; +export { Button } from './components/button/Button.component'; +export { Checkbox } from './components/checkbox/Checkbox.component'; +export { Chips } from './components/chips/Chips.component'; +export { Dropdown } from './components/dropdown/Dropdown.component'; +export { LOADER_SIZE, STATUS_CRITICAL, STATUS_WARNING, STATUS_SUCCESS, STATUS_HEALTHY, STATUS_INFO, STATUS_UNKNOWN, STATUS_NONE, Status, } from './components/constants'; +export { Layout } from './components/layout/Layout.component'; +export { Loader } from './components/loader/Loader.component'; +export { Modal } from './components/modal/Modal.component'; +export { Navbar } from './components/navbar/Navbar.component'; +export { Notifications } from './components/notifications/Notifications.component'; +export { SearchInput } from './components/searchinput/SearchInput.component'; +export { Select } from './components/select/Select.component'; +export { Sidebar } from './components/sidebar/Sidebar.component'; +export { Steppers } from './components/steppers/Steppers.component'; +export { Toggle } from './components/toggle/Toggle.component'; +export { Tooltip } from './components/tooltip/Tooltip.component'; +export { MultiSelect } from './components/multiselect/MultiSelect.component'; +export { VegaChart } from './components/vegachart/VegaChart.component'; +export { LineChart } from './components/linechart/LineChart.component'; +export { ProgressBar } from './components/progressbar/ProgressBar.component'; +export { TextArea } from './components/textarea/TextArea.component'; +export { CloudProgressBar } from './components/cloudprogressbar/CloudProgressBar.component'; +export { Sparkline } from './components/sparkline/SparkLine.component'; +export { BarChart } from './components/barchart/BarChart.component'; +export { CircularProgressBar } from './components/circularprogressbar/CircularProgressBar.component'; +export { AreaChart } from './components/areachart/AreaChart.component'; +export { CollapsiblePanel } from './components/collapsiblepanel/CollapsiblePanel.component'; +export { LateralNavbarLayout } from './components/lateralnavbarlayout/LateralNavbarLayout.component'; +export { GlobalHealthBar } from './components/globalhealthbar/GlobalHealthBar.component'; +export { ConstrainedText } from './components/constrainedtext/Constrainedtext.component'; +export { EmptyState } from './components/emptystate/Emptystate.component'; +export { EmptyTable } from './components/emptytable/Emptytable.component'; +export { ScrollbarWrapper } from './components/scrollbarwrapper/ScrollbarWrapper.component'; +export { ErrorPage401 } from './components/error-pages/ErrorPage401.component'; +export { ErrorPage404 } from './components/error-pages/ErrorPage404.component'; +export { ErrorPage500 } from './components/error-pages/ErrorPage500.component'; +export { ErrorPageAuth } from './components/error-pages/ErrorPageAuth.component'; +export { TextBadge } from './components/textbadge/TextBadge.component'; +export { SpacedBox } from './components/spacedbox/SpacedBox'; +export { Layout as Layout2 } from './components/layout/v2'; +export { TwoPanelLayout } from './components/layout/v2/panels'; +export { AppContainer } from './components/layout/v2/AppContainer'; +export { BasicText, SecondaryText, LargerText, EmphaseText, StatusText, LargeText, SmallerText, ChartTitleText, Text, Link, } from './components/text/Text.component'; +export { Card } from './components/card/Card.component'; +export { PrettyBytes } from './components/prettybytes/PrettyBytes.component'; +export { Icon } from './components/icon/Icon.component'; +export { StatusWrapper } from './components/statuswrapper/Statuswrapper.component'; +export { Stack, Wrap, spacing } from './spacing'; +export { Form, FormSection, FormGroup } from './components/form/Form.component'; +export { FormattedDateTime } from './components/date/FormattedDateTime'; +export { getDateDaysDiff } from './components/date/dateDiffer'; +export { IconHelp } from './components/IconHelper'; +export { Dropzone } from './components/dropzone/Dropzone'; +export { Toast } from './components/toast/Toast.component'; +export { ToastProvider, useToast } from './components/toast/ToastProvider'; +export { useMutationsHandler } from './components/toast/useMutationsHandler'; +export { Stepper } from './components/steppers/Stepper.component'; +export { InfoMessage } from './components/infomessage/InfoMessage.component'; +export { InputList } from './components/inputlist/InputList.component'; +export { InlineInput } from './components/inlineinput/InlineInput'; +export { UnsuccessfulResult } from './components/UnsuccessfulResult.component'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map new file mode 100644 index 0000000000..997594a63b --- /dev/null +++ b/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACpE,OAAO,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,MAAM,GACP,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,oDAAoD,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0DAA0D,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gEAAgE,CAAC;AACrG,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0DAA0D,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gEAAgE,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,MAAM,wDAAwD,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,MAAM,wDAAwD,CAAC;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0DAA0D,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACnE,OAAO,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,WAAW,EACX,cAAc,EACd,IAAI,EACJ,IAAI,GACL,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,kCAAkC,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,kCAAkC,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,oDAAoD,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000000..08a7f82987 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,63 @@ +export { Banner } from './components/banner/Banner.component'; +export { Breadcrumb } from './components/breadcrumb/Breadcrumb.component'; +export { Button } from './components/button/Button.component'; +export { Checkbox } from './components/checkbox/Checkbox.component'; +export { Chips } from './components/chips/Chips.component'; +export { Dropdown } from './components/dropdown/Dropdown.component'; +export { LOADER_SIZE, STATUS_CRITICAL, STATUS_WARNING, STATUS_SUCCESS, STATUS_HEALTHY, STATUS_INFO, STATUS_UNKNOWN, STATUS_NONE, } from './components/constants'; +export { Layout } from './components/layout/Layout.component'; +export { Loader } from './components/loader/Loader.component'; +export { Modal } from './components/modal/Modal.component'; +export { Navbar } from './components/navbar/Navbar.component'; +export { Notifications } from './components/notifications/Notifications.component'; +export { SearchInput } from './components/searchinput/SearchInput.component'; +export { Select } from './components/select/Select.component'; +export { Sidebar } from './components/sidebar/Sidebar.component'; +export { Steppers } from './components/steppers/Steppers.component'; +export { Toggle } from './components/toggle/Toggle.component'; +export { Tooltip } from './components/tooltip/Tooltip.component'; +export { MultiSelect } from './components/multiselect/MultiSelect.component'; +export { VegaChart } from './components/vegachart/VegaChart.component'; +export { LineChart } from './components/linechart/LineChart.component'; +export { ProgressBar } from './components/progressbar/ProgressBar.component'; +export { TextArea } from './components/textarea/TextArea.component'; +export { CloudProgressBar } from './components/cloudprogressbar/CloudProgressBar.component'; +export { Sparkline } from './components/sparkline/SparkLine.component'; +export { BarChart } from './components/barchart/BarChart.component'; +export { CircularProgressBar } from './components/circularprogressbar/CircularProgressBar.component'; +export { AreaChart } from './components/areachart/AreaChart.component'; +export { CollapsiblePanel } from './components/collapsiblepanel/CollapsiblePanel.component'; +export { LateralNavbarLayout } from './components/lateralnavbarlayout/LateralNavbarLayout.component'; +export { GlobalHealthBar } from './components/globalhealthbar/GlobalHealthBar.component'; +export { ConstrainedText } from './components/constrainedtext/Constrainedtext.component'; +export { EmptyState } from './components/emptystate/Emptystate.component'; +export { EmptyTable } from './components/emptytable/Emptytable.component'; +export { ScrollbarWrapper } from './components/scrollbarwrapper/ScrollbarWrapper.component'; +export { ErrorPage401 } from './components/error-pages/ErrorPage401.component'; +export { ErrorPage404 } from './components/error-pages/ErrorPage404.component'; +export { ErrorPage500 } from './components/error-pages/ErrorPage500.component'; +export { ErrorPageAuth } from './components/error-pages/ErrorPageAuth.component'; +export { TextBadge } from './components/textbadge/TextBadge.component'; +export { SpacedBox } from './components/spacedbox/SpacedBox'; +export { Layout as Layout2 } from './components/layout/v2'; +export { TwoPanelLayout } from './components/layout/v2/panels'; +export { AppContainer } from './components/layout/v2/AppContainer'; +export { BasicText, SecondaryText, LargerText, EmphaseText, StatusText, LargeText, SmallerText, ChartTitleText, Text, Link, } from './components/text/Text.component'; +export { Card } from './components/card/Card.component'; +export { PrettyBytes } from './components/prettybytes/PrettyBytes.component'; +export { Icon } from './components/icon/Icon.component'; +export { StatusWrapper } from './components/statuswrapper/Statuswrapper.component'; +export { Stack, Wrap, spacing } from './spacing'; +export { Form, FormSection, FormGroup } from './components/form/Form.component'; +export { FormattedDateTime } from './components/date/FormattedDateTime'; +export { getDateDaysDiff } from './components/date/dateDiffer'; +export { IconHelp } from './components/IconHelper'; +export { Dropzone } from './components/dropzone/Dropzone'; +export { Toast } from './components/toast/Toast.component'; +export { ToastProvider, useToast } from './components/toast/ToastProvider'; +export { useMutationsHandler } from './components/toast/useMutationsHandler'; +export { Stepper } from './components/steppers/Stepper.component'; +export { InfoMessage } from './components/infomessage/InfoMessage.component'; +export { InputList } from './components/inputlist/InputList.component'; +export { InlineInput } from './components/inlineinput/InlineInput'; +export { UnsuccessfulResult } from './components/UnsuccessfulResult.component'; diff --git a/dist/next.d.ts b/dist/next.d.ts new file mode 100644 index 0000000000..f40e5b68fa --- /dev/null +++ b/dist/next.d.ts @@ -0,0 +1,16 @@ +import '@fortawesome/fontawesome-free/css/all.css'; +import './index.css'; +export { Button } from './components/buttonv2/Buttonv2.component'; +export { CopyButton } from './components/buttonv2/CopyButton.component'; +export { Tabs, Tab } from './components/tabsv2/Tabsv2.component'; +export { Table } from './components/tablev2/Tablev2.component'; +export { LineTemporalChart } from './components/linetemporalchart/LineTemporalChart.component'; +export { MetricsTimeSpanProvider, useMetricsTimeSpan, } from './components/linetemporalchart/MetricTimespanProvider'; +export { SyncedCursorCharts } from './components/vegachartv2/SyncedCursorCharts'; +export { Select } from './components/selectv2/Selectv2.component'; +export { HealthSelector } from './components/healthselectorv2/HealthSelector.component'; +export { CoreUiThemeProvider } from './components/coreuithemeprovider/CoreUiThemeProvider'; +export { Box } from './components/box/Box'; +export { Input } from './components/inputv2/inputv2'; +export { Accordion } from './components/accordion/Accordion.component'; +//# sourceMappingURL=next.d.ts.map \ No newline at end of file diff --git a/dist/next.d.ts.map b/dist/next.d.ts.map new file mode 100644 index 0000000000..d321244e6b --- /dev/null +++ b/dist/next.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/lib/next.ts"],"names":[],"mappings":"AAAA,OAAO,2CAA2C,CAAC;AACnD,OAAO,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,0CAA0C,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,sCAAsC,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,0CAA0C,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAC3F,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC"} \ No newline at end of file diff --git a/dist/next.js b/dist/next.js new file mode 100644 index 0000000000..2a0d3e77f2 --- /dev/null +++ b/dist/next.js @@ -0,0 +1,15 @@ +import '@fortawesome/fontawesome-free/css/all.css'; +import './index.css'; +export { Button } from './components/buttonv2/Buttonv2.component'; +export { CopyButton } from './components/buttonv2/CopyButton.component'; +export { Tabs, Tab } from './components/tabsv2/Tabsv2.component'; +export { Table } from './components/tablev2/Tablev2.component'; +export { LineTemporalChart } from './components/linetemporalchart/LineTemporalChart.component'; +export { MetricsTimeSpanProvider, useMetricsTimeSpan, } from './components/linetemporalchart/MetricTimespanProvider'; +export { SyncedCursorCharts } from './components/vegachartv2/SyncedCursorCharts'; +export { Select } from './components/selectv2/Selectv2.component'; +export { HealthSelector } from './components/healthselectorv2/HealthSelector.component'; +export { CoreUiThemeProvider } from './components/coreuithemeprovider/CoreUiThemeProvider'; +export { Box } from './components/box/Box'; +export { Input } from './components/inputv2/inputv2'; +export { Accordion } from './components/accordion/Accordion.component'; diff --git a/dist/organisms/attachments/AttachmentConfirmationModal.d.ts b/dist/organisms/attachments/AttachmentConfirmationModal.d.ts new file mode 100644 index 0000000000..5bc28e460a --- /dev/null +++ b/dist/organisms/attachments/AttachmentConfirmationModal.d.ts @@ -0,0 +1,23 @@ +import { ComponentType } from 'react'; +import { UseMutationOptions } from 'react-query'; +import { AttachmentOperation, AttachmentAction } from './AttachmentTypes'; +export declare function AttachmentConfirmationModal = Record>({ attachmentOperations, getAttachmentMutationOptions, resourceType, resourceName, redirectUrl, EntityIcon, cancelButtonDisabled, onCancel, onExit, }: { + attachmentOperations: AttachmentOperation[]; + getAttachmentMutationOptions: () => UseMutationOptions; + resourceName: string; + resourceType: RESOURCE_TYPE; + redirectUrl: string; + EntityIcon: ComponentType>; + cancelButtonDisabled?: boolean; + onCancel?: () => void; + onExit?: (successfullOperations: AttachmentOperation[], failedOperations: AttachmentOperation[]) => void; +}): import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=AttachmentConfirmationModal.d.ts.map \ No newline at end of file diff --git a/dist/organisms/attachments/AttachmentConfirmationModal.d.ts.map b/dist/organisms/attachments/AttachmentConfirmationModal.d.ts.map new file mode 100644 index 0000000000..0b88b65fb5 --- /dev/null +++ b/dist/organisms/attachments/AttachmentConfirmationModal.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttachmentConfirmationModal.d.ts","sourceRoot":"","sources":["../../../src/lib/organisms/attachments/AttachmentConfirmationModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAY,MAAM,OAAO,CAAC;AAGhD,OAAO,EAAe,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAQ1E,wBAAgB,2BAA2B,CACzC,WAAW,EACX,aAAa,EACb,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,EACA,oBAAoB,EACpB,4BAA4B,EAC5B,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,MAAM,GACP,EAAE;IACD,oBAAoB,EAAE,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;IACjE,4BAA4B,EAAE,MAAM,kBAAkB,CACpD,OAAO,EACP,OAAO,EACP;QACE,MAAM,EAAE,gBAAgB,CAAC;QACzB,IAAI,EAAE,WAAW,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CACF,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,aAAa,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,CACvB,KAAK,CAAC,iBAAiB,CAAC;QAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CAAA;KAAE,CAAC,CAC/D,CAAC;IACF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,CACP,qBAAqB,EAAE,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,EACjE,gBAAgB,EAAE,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,KACzD,IAAI,CAAC;CACX,2CA0QA"} \ No newline at end of file diff --git a/dist/organisms/attachments/AttachmentConfirmationModal.js b/dist/organisms/attachments/AttachmentConfirmationModal.js new file mode 100644 index 0000000000..a636c831b7 --- /dev/null +++ b/dist/organisms/attachments/AttachmentConfirmationModal.js @@ -0,0 +1,143 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { useState } from 'react'; +import { Table } from '../../components/tablev2/Tablev2.component'; +import { Box, Button } from '../../next'; +import { useMutation } from 'react-query'; +import { AttachmentAction } from './AttachmentTypes'; +import { useTheme } from 'styled-components'; +import { useHistory } from 'react-router'; +import { Icon, LargerText, Modal, SecondaryText, Stack, Wrap } from '../..'; +//The entity is the "thing" you want to attach to the resource, sorry about the naming :( +export function AttachmentConfirmationModal({ attachmentOperations, getAttachmentMutationOptions, resourceType, resourceName, redirectUrl, EntityIcon, cancelButtonDisabled, onCancel, onExit, }) { + const history = useHistory(); + const [isModalOpen, setIsModalOpen] = useState(false); + const handleClose = () => { + setIsModalOpen(false); + }; + const [attachmentOperationsStatuses, setAttachmentOperationsStatuses] = useState({}); + const attachmentMutation = useMutation({ + ...getAttachmentMutationOptions(), + onSettled: (_, error, flatEntity) => { + setAttachmentOperationsStatuses((statuses) => ({ + ...statuses, + [flatEntity.id]: error ? 'Error' : 'Success', + })); + }, + }); + const attachmentOperationsFlat = attachmentOperations.map((attachmentOperation) => { + return { + action: attachmentOperation.action, + type: attachmentOperation.entity.type, + entityName: attachmentOperation.entity.name, + id: attachmentOperation.entity.id, + completeEntity: attachmentOperation.entity.completeEntity, + }; + }); + const attach = () => { + attachmentOperationsFlat.forEach((attachmentOperationFlat) => { + if (attachmentOperationsStatuses[attachmentOperationFlat.id] === + 'Waiting for confirmation' || + attachmentOperationsStatuses[attachmentOperationFlat.id] === 'Error' || + !attachmentOperationsStatuses[attachmentOperationFlat.id]) { + setAttachmentOperationsStatuses((attachmentOperationsStatuses) => { + return { + ...attachmentOperationsStatuses, + [attachmentOperationFlat.id]: 'Waiting for confirmation', + }; + }); + attachmentMutation.mutate({ + ...attachmentOperationFlat, + }); + } + }); + }; + const isAttachNotDone = attachmentOperationsFlat.find((attachmentOperation) => !attachmentOperationsStatuses[attachmentOperation.id]); + const handleExit = () => { + if (onExit) { + const successfulOperations = Object.entries(attachmentOperationsStatuses) + .filter(([_, status]) => status === 'Success') + .flatMap(([operationId]) => { + const op = attachmentOperations.find((op) => op.entity.id === operationId); + if (op) + return [op]; + return []; + }); + const failedOperations = Object.entries(attachmentOperationsStatuses) + .filter(([_, status]) => status === 'Error') + .flatMap(([operationId]) => { + const op = attachmentOperations.find((op) => op.entity.id === operationId); + if (op) + return [op]; + return []; + }); + onExit(successfulOperations, failedOperations); + } + handleClose(); + history.push(redirectUrl); + }; + const modalFooter = () => { + return (_jsxs(Wrap, { children: [_jsx("p", {}), _jsx(_Fragment, { children: isAttachNotDone ? (_jsxs(Stack, { children: [_jsx(Button, { variant: "outline", onClick: handleClose, label: "Cancel" }), _jsx(Button, { icon: _jsx(Icon, { name: "Arrow-right" }), variant: "primary", onClick: attach, label: "Confirm", disabled: attachmentMutation.isLoading })] })) : (_jsx(Button, { icon: _jsx(Icon, { name: "Arrow-right" }), variant: "primary", onClick: () => { + handleExit(); + }, label: "Exit" })) })] })); + }; + function AttachmentList() { + const theme = useTheme(); + const columns = [ + { + Header: 'Action', + accessor: 'action', + cellStyle: { + width: '12.5%', + }, + Cell: ({ value }) => { + return value === AttachmentAction.ADD ? (_jsxs("span", { children: [_jsx(Icon, { name: "Link" }), " Attach"] })) : (_jsxs(Box, { color: theme.statusCritical, children: [_jsx(Icon, { name: "Unlink" }), " Detach"] })); + }, + }, + { + Header: 'Type', + accessor: 'type', + cellStyle: { + width: '12.5%', + }, + Cell: ({ value }) => { + return _jsx(EntityIcon, { type: value }); + }, + }, + { + Header: 'Entity name', + accessor: 'entityName', + cellStyle: { + width: '42.5%', + }, + }, + { + Header: 'Attachment status', + accessor: 'id', + cellStyle: { + width: '32.5%', + }, + Cell: ({ value: resourceId }) => { + if (attachmentOperationsStatuses[resourceId] === 'Error') { + return (_jsxs(Box, { display: "flex", gap: 8, alignItems: "center", children: [_jsx(Icon, { color: "statusCritical", name: "Times-circle" }), attachmentOperationsStatuses[resourceId], ' ', _jsx(Button, { size: "inline", onClick: attach, variant: "outline", label: "Retry" })] })); + } + if (attachmentOperationsStatuses[resourceId] === 'Success') { + return (_jsxs(Box, { display: "flex", gap: 8, alignItems: "center", children: [_jsx(Icon, { color: "statusHealthy", name: "Check-circle" }), attachmentOperationsStatuses[resourceId]] })); + } + return (_jsx(_Fragment, { children: attachmentOperationsStatuses[resourceId] || + 'Waiting for confirmation' })); + }, + }, + ]; + return (_jsxs("div", { style: { height: '25rem', width: '50rem' }, children: [_jsx("div", { children: "The following entities will be attached or detached: " }), _jsxs(Box, { display: "flex", gap: 24, alignItems: "center", children: [_jsx(SecondaryText, { children: _jsx(EntityIcon, { type: resourceType }) }), _jsx("p", { children: resourceName })] }), _jsx(Table, { columns: columns, data: attachmentOperationsFlat, defaultSortingKey: 'entityName', children: _jsx(Table.SingleSelectableContent, { rowHeight: "h32", separationLineVariant: "backgroundLevel3", children: (Rows) => { + return _jsx(_Fragment, { children: Rows }); + } }) })] })); + } + return (_jsxs(_Fragment, { children: [_jsx(Button, { label: "Cancel", variant: "outline", disabled: cancelButtonDisabled, onClick: () => { + if (onCancel) + onCancel(); + history.push(redirectUrl); + } }), _jsx(Button, { icon: _jsx(Icon, { name: "Save" }), label: "Save", onClick: () => { + setAttachmentOperationsStatuses({}); + setIsModalOpen(true); + }, variant: "primary", disabled: attachmentOperations.length === 0 }), _jsx(Modal, { close: isAttachNotDone ? handleClose : handleExit, footer: modalFooter(), isOpen: isModalOpen, title: _jsxs(Box, { display: "flex", gap: 8, children: [_jsx(LargerText, { children: _jsx(Icon, { name: "Link" }) }), _jsx(LargerText, { children: "Attachment" })] }), children: _jsx(AttachmentList, {}) })] })); +} diff --git a/dist/organisms/attachments/AttachmentTable.d.ts b/dist/organisms/attachments/AttachmentTable.d.ts new file mode 100644 index 0000000000..99bee5736b --- /dev/null +++ b/dist/organisms/attachments/AttachmentTable.d.ts @@ -0,0 +1,38 @@ +import { PropsWithChildren } from 'react'; +import { AttachableEntity, AttachmentOperation } from './AttachmentTypes'; +import { UseQueryOptions } from 'react-query'; +export type AttachmentTableProps = Record> = { + initiallyAttachedEntities: AttachableEntity[]; + initiallyAttachedEntitiesStatus: 'idle' | 'loading' | 'success' | 'error'; + initialAttachmentOperations: AttachmentOperation[]; + entityName: { + plural: string; + singular: string; + }; + getNameQuery?: (entity: AttachableEntity) => UseQueryOptions; + searchEntityPlaceholder: string; + onAttachmentsOperationsChanged: (attachmentOperations: AttachmentOperation[]) => void; + filteredEntities: { + status: 'idle'; + } | { + status: 'loading' | 'error'; + data?: { + number: number; + entities: AttachableEntity[]; + }; + } | { + status: 'success'; + data: { + number: number; + entities: AttachableEntity[]; + }; + }; + onEntitySearchChange: (search?: string) => void; +}; +export declare const AttachmentProvider: = Record>({ children, }: PropsWithChildren<{}>) => import("react/jsx-runtime").JSX.Element; +export declare const useAttachmentOperations: () => { + resetAttachmentTable: (initiallyAttachedEntities: AttachableEntity[], //Deliberately using any here because we can't use generics + initialAttachmentOperations: AttachmentOperation[]) => void; +}; +export declare const AttachmentTable: = Record>({ initiallyAttachedEntities, initiallyAttachedEntitiesStatus, initialAttachmentOperations, onAttachmentsOperationsChanged, entityName, searchEntityPlaceholder, getNameQuery, filteredEntities, onEntitySearchChange, }: AttachmentTableProps) => import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=AttachmentTable.d.ts.map \ No newline at end of file diff --git a/dist/organisms/attachments/AttachmentTable.d.ts.map b/dist/organisms/attachments/AttachmentTable.d.ts.map new file mode 100644 index 0000000000..5471a5446f --- /dev/null +++ b/dist/organisms/attachments/AttachmentTable.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttachmentTable.d.ts","sourceRoot":"","sources":["../../../src/lib/organisms/attachments/AttachmentTable.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,iBAAiB,EASlB,MAAM,OAAO,CAAC;AAef,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EAEpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAY,eAAe,EAAE,MAAM,aAAa,CAAC;AAQxD,MAAM,MAAM,oBAAoB,CAC9B,WAAW,EACX,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9D;IACF,yBAAyB,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;IACnE,+BAA+B,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAC1E,2BAA2B,EAAE,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;IACxE,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,KAC1C,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/C,uBAAuB,EAAE,MAAM,CAAC;IAChC,8BAA8B,EAAE,CAC9B,oBAAoB,EAAE,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,KAC7D,IAAI,CAAC;IACV,gBAAgB,EACZ;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAClB;QACE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;QAC5B,IAAI,CAAC,EAAE;YACL,MAAM,EAAE,MAAM,CAAC;YACf,QAAQ,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC;KACH,GACD;QACE,MAAM,EAAE,SAAS,CAAC;QAClB,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM,CAAC;YACf,QAAQ,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC;KACH,CAAC;IACN,oBAAoB,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD,CAAC;AAmFF,eAAO,MAAM,kBAAkB,GAC7B,WAAW,SAAS,OAAO,EAC3B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,2CAGrC,iBAAiB,CAAC,EAAE,CAAC,4CAmBvB,CAAC;AAEF,eAAO,MAAM,uBAAuB;0BAhCZ,CACpB,yBAAyB,EAAE,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,2DAA2D;IACpH,2BAA2B,EAAE,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,KACzD,IAAI;CAqCV,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,WAAW,EACX,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,qPAWrC,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,4CAmiB3C,CAAC"} \ No newline at end of file diff --git a/dist/organisms/attachments/AttachmentTable.js b/dist/organisms/attachments/AttachmentTable.js new file mode 100644 index 0000000000..7d6117c27d --- /dev/null +++ b/dist/organisms/attachments/AttachmentTable.js @@ -0,0 +1,373 @@ +import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; +import { createContext, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState, } from 'react'; +import { useCombobox } from 'downshift'; +import { Box, Button, Table } from '../../next'; +import { ConstrainedText, Icon, Loader, SearchInput, SecondaryText, Text, Tooltip, } from '../../index'; +import styled from 'styled-components'; +import { spacing, Stack, Wrap } from '../../spacing'; +import { AttachmentAction, } from './AttachmentTypes'; +import { useQuery } from 'react-query'; +import { EmptyCell } from '../../components/tablev2/Tablev2.component'; +import { tableRowHeight } from '../../components/tablev2/TableUtils'; +const rowHeight = 'h48'; +const MenuContainer = styled.ul ` + background-color: ${(props) => props.theme.backgroundLevel1}; + background-clip: content-box; + padding: 0; + list-style: none; + position: absolute; + width: ${(props) => props.width}; + z-index: 1; + margin: 0; + ${(props) => props.isOpen + ? ` + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + border: 1px solid ${props.theme.selectedActive}; + ` + : props.searchInputIsFocused + ? `border-bottom: 1px solid ${props.theme.selectedActive};` + : ''} + border-top: 0; + li { + padding: ${spacing.r8}; + cursor: pointer; + border-top: 1px solid ${(props) => props.theme.backgroundLevel2}; + &[aria-selected='true'] { + background: ${(props) => props.theme.highlight}; + } + } +`; +const SearchBoxContainer = styled.div ` + position: relative; + padding: ${spacing.r16}; +`; +const StyledSearchInput = styled(SearchInput) ` + flex-grow: 1; + + & > div:focus-within { + border-color: ${(props) => props.theme.selectedActive}; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom: 0; + } +`; +const AttachmentTableContainer = styled.div ` + height: 100%; +`; +const CenterredSecondaryText = styled(SecondaryText) ` + display: block; + text-align: center; + line-height: ${tableRowHeight[rowHeight]}rem; +`; +const PrivateAttachmentContext = createContext(null); +const AttachmentContext = createContext(null); +export const AttachmentProvider = ({ children, }) => { + const [resetAttachmentTable, setResetAttachementTable] = useState((_, __) => { }); + return (_jsx(PrivateAttachmentContext.Provider, { value: { setResetAttachementTable }, children: _jsx(AttachmentContext.Provider, { value: { resetAttachmentTable }, children: children }) })); +}; +export const useAttachmentOperations = () => { + const ctx = useContext(AttachmentContext); + if (ctx === null) { + throw new Error("useAttachmentOperations can't be used outside AttachmentProvider"); + } + return ctx; +}; +export const AttachmentTable = ({ initiallyAttachedEntities, initiallyAttachedEntitiesStatus, initialAttachmentOperations, onAttachmentsOperationsChanged, entityName, searchEntityPlaceholder, getNameQuery, filteredEntities, onEntitySearchChange, }) => { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + const privateAttachmentContext = useContext(PrivateAttachmentContext); + const exposedAttachmentContext = useContext(AttachmentContext); + if (!privateAttachmentContext || !exposedAttachmentContext) { + throw new Error('Cannot use AttachmentTable outside AttachmentProvider'); + } + //Desired attached entities and onAttachmentsOperationsChanged handling + const convertInitiallyAttachedEntitiesToDesiredAttachedEntities = useCallback((initiallyAttachedEntities, operations = initialAttachmentOperations) => { + return initiallyAttachedEntities + .filter((attachedEntities) => !operations.find((op) => op.entity.id === attachedEntities.id)) + .map((entity) => ({ + ...entity, + isPending: false, + action: null, + })); + }, [initialAttachmentOperations]); + const convertInitiallyAttachementOperationsToDesiredAttachedEntities = useCallback((initialAttachmentOperations) => { + return initialAttachmentOperations + .filter((op) => op.action !== AttachmentAction.REMOVE) + .map((op) => ({ + ...op.entity, + isPending: true, + action: op.action, + })); + }, []); + const [{ desiredAttachedEntities, attachmentsOperations }, dispatch] = useReducer((state, action) => { + switch (action.action) { + case 'RESET_DESIRED_ATTACHED_ENTITIES': + return { + desiredAttachedEntities: action.entities, + attachmentsOperations: action.operations, + }; + case AttachmentAction.ADD: + if (!state.desiredAttachedEntities.find((entity) => entity.id === action.entity.id)) { + const newAttachmentsOperations = [...state.attachmentsOperations]; + const existingOperationIndexOnThisEntity = state.attachmentsOperations.findIndex((operation) => operation.entity.id === action.entity.id); + //When ADD, we check if it's already exist in operations. If so, we delete the previous operation and not proceed to the ADD. + if (existingOperationIndexOnThisEntity !== -1 && + state.attachmentsOperations[existingOperationIndexOnThisEntity] + .action === AttachmentAction.REMOVE) { + newAttachmentsOperations.splice(existingOperationIndexOnThisEntity, 1); + const newState = { + ...state, + desiredAttachedEntities: [ + { ...action.entity }, + ...state.desiredAttachedEntities, + ], + attachmentsOperations: [...newAttachmentsOperations], + }; + return newState; + } + else { + const newState = { + ...state, + desiredAttachedEntities: [ + { ...action.entity, isPending: true }, + ...state.desiredAttachedEntities, + ], + attachmentsOperations: [...newAttachmentsOperations, action], + }; + return newState; + } + } + break; + case AttachmentAction.REMOVE: + if (state.desiredAttachedEntities.find((entity) => entity.id === action.entity.id)) { + const newDesiredAttachedEntities = [ + ...state.desiredAttachedEntities, + ]; + newDesiredAttachedEntities.splice(state.desiredAttachedEntities.findIndex((entity) => entity.id === action.entity.id), 1); + const newAttachmentsOperations = [...state.attachmentsOperations]; + const existingOperationIndexOnThisEntity = state.attachmentsOperations.findIndex((operation) => operation.entity.id === action.entity.id); + if (existingOperationIndexOnThisEntity !== -1 && + state.attachmentsOperations[existingOperationIndexOnThisEntity] + .action === AttachmentAction.ADD) { + newAttachmentsOperations.splice(existingOperationIndexOnThisEntity, 1); + } + else if (existingOperationIndexOnThisEntity !== -1 && + state.attachmentsOperations[existingOperationIndexOnThisEntity] + .action === AttachmentAction.REMOVE) { + return state; + } + else { + newAttachmentsOperations.push(action); + } + const newState = { + ...state, + desiredAttachedEntities: newDesiredAttachedEntities, + attachmentsOperations: newAttachmentsOperations, + }; + return newState; + } + break; + } + return state; + }, { + desiredAttachedEntities: [ + ...convertInitiallyAttachedEntitiesToDesiredAttachedEntities(initiallyAttachedEntities), + ...convertInitiallyAttachementOperationsToDesiredAttachedEntities(initialAttachmentOperations), + ], + attachmentsOperations: initialAttachmentOperations, + }); + useEffect(() => { + onAttachmentsOperationsChanged(attachmentsOperations); + }, [onAttachmentsOperationsChanged, attachmentsOperations]); + const previousInitiallyAttachedEntitiesStatus = useRef(initiallyAttachedEntitiesStatus); + useMemo(() => { + if (initiallyAttachedEntitiesStatus === 'success' && + previousInitiallyAttachedEntitiesStatus.current !== + initiallyAttachedEntitiesStatus) { + previousInitiallyAttachedEntitiesStatus.current = 'success'; + dispatch({ + action: 'RESET_DESIRED_ATTACHED_ENTITIES', + entities: [ + ...convertInitiallyAttachedEntitiesToDesiredAttachedEntities(initiallyAttachedEntities), + ...convertInitiallyAttachementOperationsToDesiredAttachedEntities(initialAttachmentOperations), + ], + operations: initialAttachmentOperations, + }); + } + else { + previousInitiallyAttachedEntitiesStatus.current = + initiallyAttachedEntitiesStatus; + } + }, [ + initiallyAttachedEntitiesStatus, + initiallyAttachedEntities, + initialAttachmentOperations, + convertInitiallyAttachedEntitiesToDesiredAttachedEntities, + convertInitiallyAttachementOperationsToDesiredAttachedEntities, + ]); + useEffect(() => { + privateAttachmentContext.setResetAttachementTable(() => { + return (newlyAttachedEntities, newAttachmentOperations) => { + dispatch({ + action: 'RESET_DESIRED_ATTACHED_ENTITIES', + entities: [ + ...convertInitiallyAttachedEntitiesToDesiredAttachedEntities(newlyAttachedEntities, newAttachmentOperations), + ...convertInitiallyAttachementOperationsToDesiredAttachedEntities(newAttachmentOperations), + ], + operations: newAttachmentOperations, + }); + }; + }); + }, [ + convertInitiallyAttachedEntitiesToDesiredAttachedEntities, + convertInitiallyAttachementOperationsToDesiredAttachedEntities, + dispatch, + ]); + const resetRef = useRef(null); + const searchInputRef = useRef(null); + const onSelectedItemChange = useCallback((onChangeParams) => { + if (onChangeParams.selectedItem) { + dispatch({ + action: AttachmentAction.ADD, + entity: onChangeParams.selectedItem, + }); + if (resetRef.current) + resetRef.current(); + if (searchInputRef.current) + searchInputRef.current.blur(); + } + }, [resetRef]); + const { isOpen, getMenuProps, getInputProps, openMenu, getItemProps, reset } = useCombobox({ + items: filteredEntities.status === 'success' + ? filteredEntities.data.entities + : [], + onSelectedItemChange, + onInputValueChange: ({ inputValue }) => { + onEntitySearchChange(inputValue); + }, + }); + useMemo(() => { + //@ts-expect-error assigning to the ref is expected here + resetRef.current = reset; + }, [reset]); + // UI styling states + const [searchWidth, setSearchWidth] = useState('0px'); + const [searchInputIsFocused, setSearchInputIsFocused] = useState(false); + return (_jsxs(Table, { columns: [ + { + Header: 'Name', + accessor: 'name', + cellStyle: { + flex: 1.5, + marginRight: '1.5rem', + }, + //@ts-expect-error + Cell: ({ value, row: { original: entity }, }) => { + const { data: asyncName, status } = useQuery({ + ...(getNameQuery + ? getNameQuery(entity) + : { queryKey: ['fakeQuery'], queryFn: () => value }), + enabled: !value, + }); + if (value) { + return _jsx(ConstrainedText, { text: value, lineClamp: 2 }); + } + if (status === 'error') { + return (_jsxs(_Fragment, { children: ["An error occured while loading ", entityName.singular, " name"] })); + } + if (status === 'loading' || status === 'idle') { + return _jsx(_Fragment, { children: "Loading..." }); + } + if (status === 'success') { + if (!asyncName) { + return _jsx(EmptyCell, {}); + } + return _jsx(ConstrainedText, { text: asyncName, lineClamp: 2 }); + } + return _jsx(EmptyCell, {}); + }, + }, + { + Header: 'Attachment', + accessor: 'isPending', + cellStyle: { + flex: 0.5, + }, + Cell: ({ value }) => { + return value ? _jsx(_Fragment, { children: "Pending" }) : _jsx(_Fragment, { children: "Attached" }); + }, + }, + { + Header: _jsx(Box, { flex: 0.5 }), + accessor: 'action', + cellStyle: { + textAlign: 'right', + flex: 0.5, + marginLeft: 'auto', + marginRight: '0.5rem', + }, + Cell: ({ row: { original: entity }, }) => (_jsx(Button, { size: "inline", onClick: () => { + dispatch({ + action: AttachmentAction.REMOVE, + entity: { + name: entity.name, + id: entity.id, + type: entity.type, + }, + }); + }, icon: _jsx(Icon, { name: "Close" }), label: "Remove", variant: "danger", disabled: !!entity.disableDetach })), + }, + ], data: desiredAttachedEntities.map((entity) => ({ + ...entity, + isPending: entity.isPending || false, + action: null, + })), defaultSortingKey: "name", children: [_jsxs(SearchBoxContainer, { ref: (element) => { + if (element === null || element === void 0 ? void 0 : element.firstElementChild) { + setSearchWidth(element.firstElementChild.getBoundingClientRect().width - + 2 + + 'px'); + } + }, children: [filteredEntities.status === 'error' ? (_jsx(Tooltip, { overlay: _jsx(_Fragment, { children: "We failed to load the entities, hence search is disabled" }), children: _jsxs(Stack, { children: [_jsx(StyledSearchInput, { autoComplete: "off", placeholder: searchEntityPlaceholder, ...getInputProps({ + ref: (element) => { + if (element) + searchInputRef.current = element; + }, + }), onFocus: () => { + openMenu(); + setSearchInputIsFocused(true); + }, onBlur: () => { + setSearchInputIsFocused(false); + }, disabled: filteredEntities.status === 'error' }), _jsx(Loader, {})] }) })) : (_jsx(StyledSearchInput, { autoComplete: "off", placeholder: searchEntityPlaceholder, ...getInputProps({ + ref: (element) => { + if (element) + searchInputRef.current = element; + }, + }), onFocus: () => { + openMenu(); + setSearchInputIsFocused(true); + }, onBlur: () => { + setSearchInputIsFocused(false); + }, searchInputIsFocused: searchInputIsFocused })), _jsxs(MenuContainer, { ...getMenuProps(), width: searchWidth, isOpen: isOpen, searchInputIsFocused: searchInputIsFocused, children: [isOpen && + filteredEntities.status === 'success' && + ((_a = filteredEntities.data) === null || _a === void 0 ? void 0 : _a.entities.map((item, index) => (_jsx("li", { ...getItemProps({ item, index }), children: _jsx(Text, { children: item.name }) }, `${item.id}${index}`)))), isOpen && filteredEntities.status === 'loading' && (_jsx("li", { children: _jsx(Text, { children: "Searching..." }) })), isOpen && filteredEntities.status === 'error' && (_jsx("li", { children: _jsx(Text, { color: "statusCritical", children: "An error occured while searching" }) })), isOpen && + filteredEntities.status === 'success' && + (((_b = filteredEntities.data) === null || _b === void 0 ? void 0 : _b.number) || 0) > + ((_c = filteredEntities.data) === null || _c === void 0 ? void 0 : _c.entities.length) && (_jsx("li", { children: _jsxs(Text, { isGentleEmphazed: true, color: "textSecondary", style: { textAlign: 'right' }, children: ["There", ' ', (((_d = filteredEntities.data) === null || _d === void 0 ? void 0 : _d.number) || 0) - + ((_e = filteredEntities.data) === null || _e === void 0 ? void 0 : _e.entities.length) === + 1 + ? 'is' + : 'are', ' ', (((_f = filteredEntities.data) === null || _f === void 0 ? void 0 : _f.number) || 0) - + ((_g = filteredEntities.data) === null || _g === void 0 ? void 0 : _g.entities.length), ' ', "more", ' ', (((_h = filteredEntities.data) === null || _h === void 0 ? void 0 : _h.number) || 0) - + ((_j = filteredEntities.data) === null || _j === void 0 ? void 0 : _j.entities.length) === + 1 + ? entityName.singular + : entityName.plural, ' ', "matching your search. Suggestion: try more specific search expression."] }) })), isOpen && + filteredEntities.status === 'success' && + ((_k = filteredEntities.data) === null || _k === void 0 ? void 0 : _k.entities.length) === 0 && (_jsx("li", { children: _jsxs(Text, { isGentleEmphazed: true, color: "textSecondary", children: ["No ", entityName.plural, " found matching your search."] }) }))] })] }), _jsx(Table.SingleSelectableContent, { rowHeight: rowHeight, separationLineVariant: "backgroundLevel2", children: (rows) => (_jsxs(_Fragment, { children: [initiallyAttachedEntitiesStatus === 'idle' || + initiallyAttachedEntitiesStatus === 'loading' ? (_jsxs(Wrap, { style: { height: `${tableRowHeight[rowHeight]}rem` }, children: [_jsx("p", {}), _jsxs(Stack, { children: [_jsx(Loader, {}), _jsxs(Text, { children: ["Loading ", entityName.plural, "..."] })] }), _jsx("p", {})] })) : initiallyAttachedEntitiesStatus === 'error' ? (_jsxs(Stack, { style: { + justifyContent: 'center', + height: `${tableRowHeight[rowHeight]}rem`, + }, children: [_jsx(Icon, { name: "Exclamation-circle", color: "statusWarning" }), _jsxs(Text, { color: "textSecondary", children: ["Failed to load attached ", entityName.plural, "."] })] })) : (desiredAttachedEntities.length === 0 && (_jsxs(CenterredSecondaryText, { children: ["No ", entityName.plural, " attached"] }))), desiredAttachedEntities.length > 0 && rows] })) })] })); +}; diff --git a/dist/organisms/attachments/AttachmentTypes.d.ts b/dist/organisms/attachments/AttachmentTypes.d.ts new file mode 100644 index 0000000000..5fb7fc2814 --- /dev/null +++ b/dist/organisms/attachments/AttachmentTypes.d.ts @@ -0,0 +1,16 @@ +export type AttachableEntity = Record> = { + name: string; + id: string; + type: ENTITY_TYPE; + disableDetach?: boolean; + completeEntity?: ENTITY; +}; +export declare enum AttachmentAction { + ADD = 0, + REMOVE = 1 +} +export type AttachmentOperation = Record> = { + action: AttachmentAction; + entity: AttachableEntity; +}; +//# sourceMappingURL=AttachmentTypes.d.ts.map \ No newline at end of file diff --git a/dist/organisms/attachments/AttachmentTypes.d.ts.map b/dist/organisms/attachments/AttachmentTypes.d.ts.map new file mode 100644 index 0000000000..083d979c61 --- /dev/null +++ b/dist/organisms/attachments/AttachmentTypes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttachmentTypes.d.ts","sourceRoot":"","sources":["../../../src/lib/organisms/attachments/AttachmentTypes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,CAC1B,WAAW,EACX,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9D;IACF,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,oBAAY,gBAAgB;IAC1B,GAAG,IAAA;IACH,MAAM,IAAA;CACP;AAED,MAAM,MAAM,mBAAmB,CAC7B,WAAW,EACX,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9D;IACF,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;CAC/C,CAAC"} \ No newline at end of file diff --git a/dist/organisms/attachments/AttachmentTypes.js b/dist/organisms/attachments/AttachmentTypes.js new file mode 100644 index 0000000000..3395b1eecf --- /dev/null +++ b/dist/organisms/attachments/AttachmentTypes.js @@ -0,0 +1,5 @@ +export var AttachmentAction; +(function (AttachmentAction) { + AttachmentAction[AttachmentAction["ADD"] = 0] = "ADD"; + AttachmentAction[AttachmentAction["REMOVE"] = 1] = "REMOVE"; +})(AttachmentAction || (AttachmentAction = {})); diff --git a/dist/spacing.d.ts b/dist/spacing.d.ts new file mode 100644 index 0000000000..5587131ba1 --- /dev/null +++ b/dist/spacing.d.ts @@ -0,0 +1,42 @@ +import { HTMLAttributes, HTMLProps, ReactNode } from 'react'; +import { BoxComponentProps } from './components/box/Box'; +export declare const spacing: { + r1: string; + r2: string; + r4: string; + r8: string; + r10: string; + r12: string; + r14: string; + r16: string; + r20: string; + r24: string; + r28: string; + r32: string; + r36: string; + r40: string; + f1: string; + f2: string; + f4: string; + f8: string; + f10: string; + f12: string; + f14: string; + f16: string; + f20: string; + f24: string; + f28: string; + f32: string; + f36: string; + f40: string; +}; +export declare const Stack: ({ gap, direction, withSeparators, children, ...rest }: { + gap?: keyof typeof spacing; + direction?: "vertical" | "horizontal"; + withSeparators?: boolean; + children: ReactNode[]; +} & HTMLAttributes) => import("react/jsx-runtime").JSX.Element; +export declare const Wrap: ({ children, ...rest }: { + children: ReactNode[]; +} & Omit, "ref" | "as"> & BoxComponentProps) => import("react/jsx-runtime").JSX.Element; +//# sourceMappingURL=spacing.d.ts.map \ No newline at end of file diff --git a/dist/spacing.d.ts.map b/dist/spacing.d.ts.map new file mode 100644 index 0000000000..d041e260bc --- /dev/null +++ b/dist/spacing.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"spacing.d.ts","sourceRoot":"","sources":["../src/lib/spacing.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAO,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BnB,CAAC;AAuBF,eAAO,MAAM,KAAK,0DAMf;IACD,GAAG,CAAC,EAAE,MAAM,OAAO,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB,GAAG,cAAc,CAAC,cAAc,CAAC,4CA0BjC,CAAC;AAEF,eAAO,MAAM,IAAI,0BAGd;IAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,GAC1E,iBAAiB,4CAQlB,CAAC"} \ No newline at end of file diff --git a/dist/spacing.js b/dist/spacing.js new file mode 100644 index 0000000000..615f79d046 --- /dev/null +++ b/dist/spacing.js @@ -0,0 +1,60 @@ +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; +import { Children } from 'react'; +import styled from 'styled-components'; +import { Box } from './components/box/Box'; +export const spacing = { + r1: '0.0625rem', + r2: '0.125rem', + r4: '0.25rem', + r8: '0.5rem', + r10: '0.625rem', + r12: '0.75rem', + r14: '0.875rem', + r16: '1rem', + r20: '1.25rem', + r24: '1.5rem', + r28: '1.75rem', + r32: '2rem', + r36: '2.25rem', + r40: '2.5rem', + f1: '1px', + f2: '2px', + f4: '4px', + f8: '8px', + f10: '10px', + f12: '12px', + f14: '14px', + f16: '16px', + f20: '20px', + f24: '24px', + f28: '28px', + f32: '32px', + f36: '36px', + f40: '40px', +}; +const HSeparator = styled.div ` + min-height: ${spacing.r40}; + min-width: ${spacing.r2}; + background: ${(props) => props.theme.border}; +`; +const VSeparator = styled.div ` + height: 1px; + width: ${spacing.r24}; + background: ${(props) => props.theme.border}; +`; +const Separator = ({ type }) => { + return (_jsxs(_Fragment, { children: [type === 'horizontal' && _jsx(HSeparator, { children: "\u00A0" }), type === 'vertical' && _jsx(VSeparator, { children: "\u00A0" })] })); +}; +export const Stack = ({ gap, direction, withSeparators, children, ...rest }) => { + gap = gap || 'r8'; + direction = direction || 'horizontal'; + const numberOfChildren = Children.count(children); + return (_jsx(Box, { display: 'flex', flexDirection: direction === 'horizontal' ? 'row' : 'column', alignItems: direction === 'horizontal' ? 'center' : 'normal', gap: spacing[gap], ...rest, children: Children.map(children, (node, nodeIndex) => { + return (_jsxs(_Fragment, { children: [node, withSeparators && nodeIndex + 1 !== numberOfChildren && (_jsx(Separator, { type: direction }))] })); + }) })); +}; +export const Wrap = ({ children, ...rest }) => { + return (_jsx(Box, { display: 'flex', justifyContent: "space-between", ...rest, children: Children.map(children, (node) => { + return _jsx(_Fragment, { children: node }); + }) })); +}; diff --git a/dist/style/fonts/Lato-Bold.woff b/dist/style/fonts/Lato-Bold.woff new file mode 100644 index 0000000000..c6dff51f06 Binary files /dev/null and b/dist/style/fonts/Lato-Bold.woff differ diff --git a/dist/style/fonts/Lato-Bold.woff2 b/dist/style/fonts/Lato-Bold.woff2 new file mode 100644 index 0000000000..bb195043cf Binary files /dev/null and b/dist/style/fonts/Lato-Bold.woff2 differ diff --git a/dist/style/fonts/Lato-Regular.woff b/dist/style/fonts/Lato-Regular.woff new file mode 100644 index 0000000000..ae1307ff5f Binary files /dev/null and b/dist/style/fonts/Lato-Regular.woff differ diff --git a/dist/style/fonts/Lato-Regular.woff2 b/dist/style/fonts/Lato-Regular.woff2 new file mode 100644 index 0000000000..3bf9843328 Binary files /dev/null and b/dist/style/fonts/Lato-Regular.woff2 differ diff --git a/dist/style/theme.d.ts b/dist/style/theme.d.ts new file mode 100644 index 0000000000..f1f24db15a --- /dev/null +++ b/dist/style/theme.d.ts @@ -0,0 +1,160 @@ +export declare const hotPink = "#E40046"; +export declare const pink = "#EB4962"; +export declare const lightPink = "#F5B5BA"; +export declare const plum = "#8A1B61"; +export declare const jade = "#006F62"; +export declare const lightBeige = "#FAF7F5"; +export declare const warmRed = "#EF3340"; +export declare const turquoise = "#00B2A9"; +export declare const yellowOrange = "#F1B434"; +export declare const mediumOrange = "#FF8F1C"; +export declare const yellow = "#EFC93D"; +export declare const green = "#228F67"; +export declare const white = "#ffffff"; +export declare const black = "#000000"; +export declare const blackLight = "#313B44"; +export declare const blueDarkest = "#0F3554"; +export declare const blueDarker = "#144A75"; +export declare const blueDark = "#1F73B7"; +export declare const blue = "#337FBD"; +export declare const blueLight = "#5293C7"; +export declare const blueLighter = "#ADCCE4"; +export declare const blueLightest = "#CEE2F2"; +export declare const grayDarkest = "#2F3941"; +export declare const grayDarker = "#49545C"; +export declare const grayDark = "#68737D"; +export declare const gray = "#87929D"; +export declare const grayLight = "#C2C8CC"; +export declare const grayLighter = "#D8DCDE"; +export declare const grayLightest = "#E9EBED"; +export type CoreUITheme = { + statusHealthy: string; + statusHealthyRGB: string; + statusWarning: string; + statusWarningRGB: string; + statusCritical: string; + statusCriticalRGB: string; + selectedActive: string; + highlight: string; + border: string; + buttonPrimary: string; + buttonSecondary: string; + buttonDelete: string; + infoPrimary: string; + infoSecondary: string; + backgroundLevel1: string; + backgroundLevel2: string; + backgroundLevel3: string; + backgroundLevel4: string; + textPrimary: string; + textSecondary: string; + textTertiary: string; + textReverse: string; + textLink: string; +}; +export declare const coreUIAvailableThemesNames: readonly ["darkRebrand", "artescaLight", "ring9dark"]; +export type CoreUIThemeName = (typeof coreUIAvailableThemesNames)[number]; +export declare const coreUIAvailableThemes: Record; +/** + * @deprecated + * + * Please use coreUIAvailableThemes instead, the label is more explicit. + * + * import { coreUIAvailableThemes } from '@scality/core-ui/dist/style/theme'; + */ +export declare const defaultTheme: Record<"darkRebrand" | "artescaLight" | "ring9dark", CoreUITheme>; +export declare const brand: CoreUITheme; +export type ThemeColors = keyof CoreUITheme; +export declare const lineColor1 = "#A14FBF"; +export declare const lineColor2 = "#BE9A40"; +export declare const lineColor3 = "#4BE4E2"; +export declare const lineColor4 = "#245A83"; +export declare const lineColor5 = "#E3FF73"; +export declare const lineColor6 = "#BE2543"; +export declare const lineColor7 = "#FD8144"; +export declare const lineColor8 = "#F6B187"; +export declare const fontSize: { + smaller: string; + small: string; + base: string; + large: string; + larger: string; + huge: string; + massive: string; +}; +/** + * @deprecated + * + * use import { spacing } from '@scality/core-ui/dist/spacing'; + */ +export declare const space: string[]; +export declare const fontWeight: { + light: string; + base: string; + semibold: string; + bold: string; +}; +/** + * @deprecated + * + * Use spacing instead \ + * smaller : sp4 \ + * small : sp8 \ + * base : sp16 \ + * large : sp20 \ + * larger : sp24 \ + * + */ +export declare const padding: { + smaller: string; + small: string; + base: string; + large: string; + larger: string; +}; +/** + * @deprecated + * use import { spacing } from '@scality/core-ui/dist/spacing'; + * + */ +export declare const spacing: { + sp0: string; + sp1: string; + sp2: string; + sp4: string; + sp8: string; + sp10: string; + sp12: string; + sp14: string; + sp16: string; + sp20: string; + sp24: string; + sp28: string; + sp32: string; + sp40: string; +}; +export declare const svgSize: { + smaller: string; + small: string; + base: string; + large: string; + larger: string; + huge: string; + massive: string; +}; +export declare const zIndex: { + tooltip: number; + notification: number; + modal: number; + overlay: number; + dropdown: number; + nav: number; + sidebar: number; + scrollbarButton: number; + base: number; +}; +export declare const navbarHeight = "3rem"; +export declare const navbarItemWidth = "4.286rem"; +export declare const sidebarItemHeight: string; +export declare const sidebarWidth: string; +//# sourceMappingURL=theme.d.ts.map \ No newline at end of file diff --git a/dist/style/theme.d.ts.map b/dist/style/theme.d.ts.map new file mode 100644 index 0000000000..6dd71cd9b9 --- /dev/null +++ b/dist/style/theme.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/style/theme.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,QAAQ,YAAY,CAAC;AAClC,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,QAAQ,YAAY,CAAC;AAClC,eAAO,MAAM,IAAI,YAAY,CAAC;AAC9B,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,YAAY,YAAY,CAAC;AAEtC,MAAM,MAAM,WAAW,GAAG;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,0BAA0B,uDAI7B,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,EAAE,WAAW,CA4EtE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,mEAAwB,CAAC;AAGlD,eAAO,MAAM,KAAK,aAAoC,CAAC;AAEvD,MAAM,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC;AAE5C,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,QAAQ;;;;;;;;CASpB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,KAAK,UAejB,CAAC;AACF,eAAO,MAAM,UAAU;;;;;CAKtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO;;;;;;CAMnB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;CAenB,CAAC;AAEF,eAAO,MAAM,OAAO;;;;;;;;CAQnB,CAAC;AACF,eAAO,MAAM,MAAM;;;;;;;;;;CAUlB,CAAC;AAEF,eAAO,MAAM,YAAY,SAAS,CAAC;AACnC,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C,eAAO,MAAM,iBAAiB,QAAe,CAAC;AAC9C,eAAO,MAAM,YAAY,QAAe,CAAC"} \ No newline at end of file diff --git a/dist/style/theme.js b/dist/style/theme.js new file mode 100644 index 0000000000..e516d6dff6 --- /dev/null +++ b/dist/style/theme.js @@ -0,0 +1,234 @@ +//== Colors +export const hotPink = '#E40046'; +export const pink = '#EB4962'; +export const lightPink = '#F5B5BA'; +export const plum = '#8A1B61'; +export const jade = '#006F62'; +export const lightBeige = '#FAF7F5'; +export const warmRed = '#EF3340'; +export const turquoise = '#00B2A9'; +export const yellowOrange = '#F1B434'; +export const mediumOrange = '#FF8F1C'; +export const yellow = '#EFC93D'; +export const green = '#228F67'; +export const white = '#ffffff'; +export const black = '#000000'; +export const blackLight = '#313B44'; +export const blueDarkest = '#0F3554'; +export const blueDarker = '#144A75'; +export const blueDark = '#1F73B7'; +export const blue = '#337FBD'; +export const blueLight = '#5293C7'; +export const blueLighter = '#ADCCE4'; +export const blueLightest = '#CEE2F2'; +export const grayDarkest = '#2F3941'; +export const grayDarker = '#49545C'; +export const grayDark = '#68737D'; +export const gray = '#87929D'; +export const grayLight = '#C2C8CC'; +export const grayLighter = '#D8DCDE'; +export const grayLightest = '#E9EBED'; +export const coreUIAvailableThemesNames = [ + 'darkRebrand', + 'artescaLight', + 'ring9dark', +]; +export const coreUIAvailableThemes = { + darkRebrand: { + statusHealthy: '#0AADA6', + statusHealthyRGB: '10,173,166', + statusWarning: '#F8F32B', + statusWarningRGB: '248,243,43', + statusCritical: '#E84855', + statusCriticalRGB: '232,72,85', + selectedActive: '#037AFF', + highlight: '#1A3C75', + border: '#4A4A4A', + buttonPrimary: '#2F4185', + buttonSecondary: '#595A78', + buttonDelete: '#3D0808', + infoPrimary: '#8E8EAC', + infoSecondary: '#333366', + backgroundLevel1: '#121219', + backgroundLevel2: '#323245', + backgroundLevel3: '#232331', + backgroundLevel4: '#1B1B27', + textPrimary: '#EAEAEA', + textSecondary: '#B5B5B5', + textTertiary: '#DFDFDF', + textReverse: '#000000', + textLink: '#71AEFF', + }, + artescaLight: { + statusHealthy: '#009E93', + statusHealthyRGB: '0, 158, 147', + statusWarning: '#E77B00', + statusWarningRGB: '231, 123, 0', + statusCritical: '#C10004', + statusCriticalRGB: '193, 0, 4', + selectedActive: '#63A9D4', + highlight: '#E3F2FD', + border: '#A9A9A9', + buttonPrimary: '#ABB4F5', + buttonSecondary: '#B8BCCD', + buttonDelete: '#FFCDD2', + infoPrimary: '#5C486D', + infoSecondary: '#E2D0E2', + backgroundLevel1: '#FCFCFC', + backgroundLevel2: '#F0F0F4', + backgroundLevel3: '#E4E6EC', + backgroundLevel4: '#FAFAF6', + textPrimary: '#0D0D0D', + textSecondary: '#4F506D', + textTertiary: '#DFDFDF', // TO CHECK + textReverse: '#EAEAEA', + textLink: '#1349C5', + }, + ring9dark: { + statusHealthy: '#2BAB51', + statusHealthyRGB: '43,171,81', + statusWarning: '#FC8A32', + statusWarningRGB: '252,138,50', + statusCritical: '#E84855', + statusCriticalRGB: '232,72,85', + selectedActive: '#2196F3', + highlight: '#1A3C75', + border: '#313131', + buttonPrimary: '#2E67AB', + buttonSecondary: '#434343', + buttonDelete: '#3D0808', + infoPrimary: '#76828F', + infoSecondary: '#2C3238', + backgroundLevel1: '#120F0F', + backgroundLevel2: '#272020', + backgroundLevel3: '#201B1A', + backgroundLevel4: '#191515', + textPrimary: '#EAEAEA', + textSecondary: '#A4ACB4', + textTertiary: '#DFDFDF', + textReverse: '#000000', + textLink: '#71AEFF', + }, +}; +/** + * @deprecated + * + * Please use coreUIAvailableThemes instead, the label is more explicit. + * + * import { coreUIAvailableThemes } from '@scality/core-ui/dist/style/theme'; + */ +export const defaultTheme = coreUIAvailableThemes; +// Why use this and not directly coreUIAvailableThemes.darkRebrand ? +export const brand = coreUIAvailableThemes.darkRebrand; +// LineChart colors +export const lineColor1 = '#A14FBF'; +export const lineColor2 = '#BE9A40'; +export const lineColor3 = '#4BE4E2'; +export const lineColor4 = '#245A83'; +export const lineColor5 = '#E3FF73'; +export const lineColor6 = '#BE2543'; +export const lineColor7 = '#FD8144'; +export const lineColor8 = '#F6B187'; +export const fontSize = { + smaller: '0.71rem', + small: '0.85rem', + base: '1rem', + large: '1.14rem', + larger: '1.43rem', + huge: '1.57rem', + // no use case for the moment + massive: '1.71rem', // no use case for the moment +}; +/** + * @deprecated + * + * use import { spacing } from '@scality/core-ui/dist/spacing'; + */ +export const space = [ + '0', + '0.071rem', + '0.143rem', + '0.286rem', + '0.571rem', + '0.71rem', + '0.857rem', + '1rem', + '1.143rem', + '1.429rem', + '1.714rem', + '2rem', + '2.286rem', + '2.857rem', +]; +export const fontWeight = { + light: '400', + base: '400', + semibold: '600', + bold: '700', +}; +/** + * @deprecated + * + * Use spacing instead \ + * smaller : sp4 \ + * small : sp8 \ + * base : sp16 \ + * large : sp20 \ + * larger : sp24 \ + * + */ +export const padding = { + smaller: '4px', + small: '8px', + base: '16px', + large: '20px', + larger: '24px', +}; +/** + * @deprecated + * use import { spacing } from '@scality/core-ui/dist/spacing'; + * + */ +export const spacing = { + sp0: space[0], + sp1: space[1], + sp2: space[2], + sp4: space[3], + sp8: space[4], + sp10: space[5], + sp12: space[6], + sp14: space[7], + sp16: space[8], + sp20: space[9], + sp24: space[10], + sp28: space[11], + sp32: space[12], + sp40: space[13], +}; +// Svg size +export const svgSize = { + smaller: '11px', + small: '14px', + base: '16px', + large: '18px', + larger: '22px', + huge: '30px', + massive: '40px', +}; +export const zIndex = { + tooltip: 9990, + notification: 9000, + modal: 8500, + overlay: 8000, + dropdown: 7000, + nav: 500, + sidebar: 100, + scrollbarButton: 2, + base: 1, +}; +//navbar +export const navbarHeight = '3rem'; +export const navbarItemWidth = '4.286rem'; +//sidebar +export const sidebarItemHeight = spacing.sp40; +export const sidebarWidth = spacing.sp40; diff --git a/dist/testUtils.d.ts b/dist/testUtils.d.ts new file mode 100644 index 0000000000..5f277ef0bb --- /dev/null +++ b/dist/testUtils.d.ts @@ -0,0 +1,8 @@ +import { QueryClient } from 'react-query'; +export declare const getWrapper: () => { + Wrapper: ({ children }: { + children: React.ReactNode; + }) => import("react/jsx-runtime").JSX.Element; + queryClient: QueryClient; +}; +//# sourceMappingURL=testUtils.d.ts.map \ No newline at end of file diff --git a/dist/testUtils.d.ts.map b/dist/testUtils.d.ts.map new file mode 100644 index 0000000000..e612b2a4a4 --- /dev/null +++ b/dist/testUtils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/lib/testUtils.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAI/D,eAAO,MAAM,UAAU;4BAEU;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE;;CAW7D,CAAC"} \ No newline at end of file diff --git a/dist/testUtils.js b/dist/testUtils.js new file mode 100644 index 0000000000..1efadd6229 --- /dev/null +++ b/dist/testUtils.js @@ -0,0 +1,11 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import { QueryClient, QueryClientProvider } from 'react-query'; +import { ThemeProvider } from 'styled-components'; +import { coreUIAvailableThemes } from './style/theme'; +export const getWrapper = () => { + const queryClient = new QueryClient(); + const Wrapper = ({ children }) => { + return (_jsx(ThemeProvider, { theme: coreUIAvailableThemes.darkRebrand, children: _jsx(QueryClientProvider, { client: queryClient, children: children }) })); + }; + return { Wrapper: Wrapper, queryClient: queryClient }; +}; diff --git a/dist/utils.d.ts b/dist/utils.d.ts new file mode 100644 index 0000000000..454ba35445 --- /dev/null +++ b/dist/utils.d.ts @@ -0,0 +1,9 @@ +/** Translates the old colors into new colors while keeping the same name. + * New names are also supported. */ +export declare const getThemePropSelector: (key: any) => (props: any) => any; +/** Translates the old colors into new colors while keeping same name. + * New names are also supported. */ +export declare const getThemeVariantSelector: () => (props: any) => any; +export declare const hex2RGB: (str: string) => [number, number, number]; +export declare const convertRemToPixels: (rem: number) => number; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/dist/utils.d.ts.map b/dist/utils.d.ts.map new file mode 100644 index 0000000000..fc036288ba --- /dev/null +++ b/dist/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.ts"],"names":[],"mappings":"AAYA;mCACmC;AACnC,eAAO,MAAM,oBAAoB,mCAGhC,CAAC;AAEF;mCACmC;AACnC,eAAO,MAAM,uBAAuB,2BAInC,CAAC;AAEF,eAAO,MAAM,OAAO,QAAS,MAAM,KAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAc5D,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAS,MAAM,KAAG,MAahD,CAAC"} \ No newline at end of file diff --git a/dist/utils.js b/dist/utils.js new file mode 100644 index 0000000000..bfdfb890be --- /dev/null +++ b/dist/utils.js @@ -0,0 +1,46 @@ +const RGB_HEX = /^#?(?:([\da-f]{3})[\da-f]?|([\da-f]{6})(?:[\da-f]{2})?)$/i; +/** Ensure the consistency of colors between old and new colors */ +const variantMapping = { + healthy: 'statusHealthy', + success: 'statusHealthy', + warning: 'statusWarning', + danger: 'statusCritical', + selected: 'selectedActive', + base: 'infoPrimary', +}; +/** Translates the old colors into new colors while keeping the same name. + * New names are also supported. */ +export const getThemePropSelector = (key) => (props) => { + var _a; + const key_ = (_a = variantMapping[key]) !== null && _a !== void 0 ? _a : key; + return props.theme[key_]; +}; +/** Translates the old colors into new colors while keeping same name. + * New names are also supported. */ +export const getThemeVariantSelector = () => (props) => { + var _a; + const theme = props.theme; + const key = (_a = variantMapping[props.variant]) !== null && _a !== void 0 ? _a : props.variant; + return theme[key]; +}; +export const hex2RGB = (str) => { + const [, short, long] = String(str).match(RGB_HEX) || []; + if (long) { + const value = Number.parseInt(long, 16); + return [value >> 16, (value >> 8) & 0xff, value & 0xff]; + } + else if (short) { + const [r, g, b] = Array.from(short, (s) => Number.parseInt(s, 16)).map((n) => (n << 4) | n); + return [r, g, b]; + } + throw new Error('Invalid hex string provided'); +}; +export const convertRemToPixels = (rem) => { + if (document.documentElement && + rem && + Number.isFinite(rem) && + !Number.isNaN(rem)) { + return (rem * parseFloat(getComputedStyle(document.documentElement).fontSize) || 0); + } + return 0; +};