Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,11 @@ const meta = {
},
size: {
description: 'Size',
defaultValue: 'medium',
options: ['medium', 'small'],
control: { type: 'radio' },
},
variant: {
description: 'Variant',
defaultValue: 'primary',
options: ['primary', 'secondary'],
control: { type: 'radio' },
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.collapse {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.3s;
overflow: hidden;

&:global(.is-open) {
grid-template-rows: 1fr;
}

&__inner {
min-height: 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import Collapse from './Collapse';
import Button from '@uikit/Button/Button';

const meta = {
title: 'uikit/Collapse',
component: Collapse,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
layout: 'padded',
},
} as Meta<typeof Collapse>;

export default meta;

type Story = StoryObj<typeof meta>;

const style = {
color: '#757b81',
border: '1px solid #757b81',
marginTop: '20px',
padding: '16px',
};

const CollapseEasy: React.FC = () => {
const [isExpanded, setExpanded] = useState(true);
return (
<>
<Button
onClick={() => {
setExpanded((prevExpanded) => !prevExpanded);
}}
>
{isExpanded ? 'Close' : 'Open'}
</Button>
<Collapse isExpanded={isExpanded}>
<div style={style}>
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, <br />
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<br />
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi <br />
ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
<br />
in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
<br />
Excepteur sint occaecat cupidatat non proident, <br />
sunt in culpa qui officia deserunt mollit anim id est laborum."
<br />
<br />
<br />
</div>
</Collapse>
</>
);
};

export const CollapseExample: Story = {
render: (args) => {
return <CollapseEasy {...args} />;
},
};
36 changes: 36 additions & 0 deletions smart-frontend/app/src/components/uikit/Collapse/Collapse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import cn from 'classnames';
import s from './Collapse.module.scss';

interface CollapseProps extends React.HTMLAttributes<HTMLDivElement> {
isExpanded: boolean;
}

const Collapse: React.FC<CollapseProps> = ({ isExpanded, children, className, ...props }) => {
const classes = cn(className, s.collapse, { 'is-open': isExpanded });

return (
<div className={classes} {...props}>
<div className={s.collapse__inner}>{children}</div>
</div>
);
};

export default Collapse;
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const DateRangePickerPanel: React.FC<DateRangePickerPanelProps> = ({

return (
<div data-test="data-picker-panel">
<TabsBlock>
<TabsBlock variant="secondary">
<TabButton onClick={getHandleTabClick('range')} isActive={activeTab === 'range'}>
Range
</TabButton>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions smart-frontend/app/src/components/uikit/Icon/sprite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
export const allowIconsNames = [
//
'arrow-sorting',
'chevron-double',
'chevron',
'close',
Expand All @@ -29,6 +30,7 @@ export const allowIconsNames = [
'status-info',
'status-ok',
'status-warning',
'table-filter',
'user',
] as const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ export interface LabeledFieldProps extends React.HTMLAttributes<HTMLDivElement>
disabled?: boolean;
hint?: ReactNode;
direction?: 'column' | 'row';
dataTest?: string;
}

const LabeledField = React.forwardRef<HTMLDivElement, LabeledFieldProps>(
({ label, hint = '', className, disabled = false, direction = 'column', children, dataTest, ...props }, ref) => {
({ label, hint = '', className, disabled = false, direction = 'column', children, ...props }, ref) => {
const labeledFieldClasses = cn(
s.labeledField,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,57 @@
* limitations under the License.
*/
import React, { useRef } from 'react';
import cn from 'classnames';
import type { InputProps } from '@uikit/Input/Input';
import Input from '@uikit/Input/Input';
import { useForwardRef } from '@hooks/useForwardRef';
import { createChangeEvent } from '@utils/handlerUtils';
import IconButton from '@uikit/IconButton/IconButton';

const SearchInput = React.forwardRef<HTMLInputElement, InputProps>(({ className, ...props }, ref) => {
const localRef = useRef<HTMLInputElement>(null);
const reference = useForwardRef(ref, localRef);

const handleIconClick = () => {
if (props.value && localRef.current) {
const event = createChangeEvent(localRef.current);
event.target.value = '';
props.onChange?.(event);
}
};

return (
<Input
{...props}
className={cn(className, 'search-input')}
ref={reference}
endAdornment={
<IconButton icon={props.value ? 'close' : 'search'} onClick={handleIconClick} size={12} variant="secondary" />
export type SearchInputProps = Omit<InputProps, 'endAdornment'> & {
denyCharsPattern?: RegExp;
};

const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
({ denyCharsPattern, onChange, ...props }, ref) => {
const localRef = useRef<HTMLInputElement>(null);
const reference = useForwardRef(ref, localRef);

const handleIconClick = () => {
if (props.value && localRef.current) {
const event = createChangeEvent(localRef.current);
event.target.value = '';
onChange?.(event);
}
size="medium"
/>
);
});
};

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (denyCharsPattern) {
const regExp = new RegExp(denyCharsPattern, 'g');
if (regExp.test(e.target.value)) {
const newValue = e.target.value.replace(regExp, '');
// if after remove deny chars value not changed - not dispatch event
if (newValue === props.value) return;

e.target.value = newValue;
}
}

onChange?.(e);
};

return (
<Input
{...props}
onChange={handleInputChange}
ref={reference}
endAdornment={
<IconButton icon={props.value ? 'close' : 'search'} onClick={handleIconClick} size={12} variant="secondary" />
}
size="medium"
/>
);
},
);

SearchInput.displayName = 'SearchInput';
export default SearchInput;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
:global {
body.theme-dark {
--sortingLabel-color-hover: var(--color-offWhite);
}
body.theme-light {
--sortingLabel-color-hover: var(--color-blue);
}
}

.sortingLabel {
display: inline-flex;
align-items: center;
gap: 4px;
cursor: pointer;
transition: color 250ms;

&__arrow {
&_desc {
transform: rotate(180deg);
}
}

&:not(:global(.is-sorted)):not(:hover) &__arrow {
visibility: hidden;
}

&:hover {
color: var(--sortingLabel-color-hover);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import cn from 'classnames';
import type { SortingProps, SortParams } from '@models/table';
import Icon from '@uikit/Icon/Icon';
import s from './SortingLabel.module.scss';

interface SortingLabelProps extends Partial<SortingProps> {
children: React.ReactNode;
name: string;
isSorted?: boolean;
}

const revertOrder = (order: SortParams['sortDirection']) => (order === 'asc' ? 'desc' : 'asc');

const SortingLabel: React.FC<SortingLabelProps> = ({ children, onSorting, name, sortParams }) => {
const isSorted = name === sortParams?.sortBy;

const wrapClasses = cn(s.sortingLabel, {
'is-sorted': isSorted,
});

const arrowClasses = cn(
s.sortingLabel__arrow,
s[`sortingLabel__arrow_${(isSorted ? sortParams?.sortDirection : undefined) ?? 'asc'}`],
);

const handleClick = () => {
const newSortDirection = isSorted ? revertOrder(sortParams.sortDirection) : 'asc';
onSorting?.({ sortBy: name, sortDirection: newSortDirection });
};

return (
<div className={wrapClasses} onClick={handleClick} data-test="sorting">
<div className={s.sortingLabel__label}>{children}</div>
<Icon name="arrow-sorting" size={14} className={arrowClasses} />
</div>
);
};

export default SortingLabel;
Loading