-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(file-upload): implement component
- Loading branch information
Showing
40 changed files
with
2,284 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ const componentNames = [ | |
'select', | ||
'modal', | ||
'card', | ||
'file-upload', | ||
//--generator-anchor-- | ||
]; | ||
|
||
|
23 changes: 23 additions & 0 deletions
23
packages/ods/react/tests/_app/src/components/ods-file-upload.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React, { useState } from 'react'; | ||
import { type OdsFile, type OdsFileCancelEvent, type OdsFileChangeEvent } from '@ovhcloud/ods-components'; | ||
import { OdsFileUpload } from 'ods-components-react'; | ||
|
||
const FileUpload = () => { | ||
const [files, setFiles] = useState<OdsFile[]>([]); | ||
|
||
function onFileCancel(event: OdsFileCancelEvent) { | ||
setFiles(() => files.filter((file) => file.odsId !== event.detail.odsId)); | ||
} | ||
|
||
function onFileChange(event: OdsFileChangeEvent) { | ||
setFiles(() => files.concat(event.detail)); | ||
} | ||
|
||
return ( | ||
<OdsFileUpload files={ files } | ||
onOdsFileCancel={ onFileCancel } | ||
onOdsFileChange={ onFileChange } /> | ||
); | ||
}; | ||
|
||
export default FileUpload; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import type { Page } from 'puppeteer'; | ||
import { goToComponentPage, setupBrowser } from '../setup'; | ||
|
||
describe('ods-file-upload react', () => { | ||
const setup = setupBrowser(); | ||
let page: Page; | ||
|
||
beforeAll(async () => { | ||
page = setup().page; | ||
}); | ||
|
||
beforeEach(async () => { | ||
await goToComponentPage(page, 'ods-file-upload'); | ||
}); | ||
|
||
it('render the component correctly', async () => { | ||
const elem = await page.$('ods-file-upload'); | ||
const boundingBox = await elem?.boundingBox(); | ||
|
||
expect(boundingBox?.height).toBeGreaterThan(0); | ||
expect(boundingBox?.width).toBeGreaterThan(0); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Local Stencil command generates external ods component build at the root of the project | ||
# Excluding them is a temporary solution to avoid pushing generated files | ||
# But the issue may cause main build (ods-component package) to fails, as it detects multiples occurences | ||
# of the same component and thus you have to delete all those generated dir manually | ||
*/src/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "@ovhcloud/ods-component-file-upload", | ||
"version": "17.1.0", | ||
"private": true, | ||
"description": "ODS FileUpload component", | ||
"main": "dist/index.cjs.js", | ||
"collection": "dist/collection/collection-manifest.json", | ||
"scripts": { | ||
"clean": "rimraf .stencil coverage dist docs-api www", | ||
"doc": "typedoc --pretty --plugin ../../../scripts/typedoc-plugin-decorator.js && node ../../../scripts/generate-typedoc-md.js", | ||
"lint:scss": "stylelint 'src/components/**/*.scss'", | ||
"lint:ts": "eslint '{src,tests}/**/*.{js,ts,tsx}'", | ||
"start": "stencil build --dev --watch --serve", | ||
"test:e2e": "stencil test --e2e --runInBand --config stencil.config.ts", | ||
"test:e2e:ci": "tsc --noEmit && stencil test --e2e --ci --runInBand --config stencil.config.ts", | ||
"test:spec": "stencil test --spec --config stencil.config.ts --coverage", | ||
"test:spec:ci": "tsc --noEmit && stencil test --config stencil.config.ts --spec --ci --coverage" | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
.../src/components/file-upload/src/components/ods-file-upload-item/ods-file-upload-item.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
@use 'sass:math'; | ||
@use '../../../../../style/font'; | ||
@use '../../../../../style/input'; | ||
@use '../ods-file-upload/ods-file-upload' as file-upload; | ||
|
||
:host(.ods-file-upload-item) { | ||
display: grid; | ||
grid-template-columns: max-content 1fr; | ||
column-gap: 8px; | ||
align-items: flex-start; | ||
padding: 0 file-upload.$ods-file-upload-padding; | ||
color: var(--ods-color-text); | ||
} | ||
|
||
:host(.ods-file-upload-item--disabled) { | ||
@include input.ods-input-disabled(); | ||
|
||
.ods-file-upload-item__icon { | ||
color: var(--ods-form-element-foreground-color-disabled); | ||
} | ||
} | ||
|
||
.ods-file-upload-item { | ||
&__icon { | ||
margin-top: math.div(file-upload.$ods-file-upload-spacing, 2); | ||
color: var(--ods-color-primary-500); | ||
font-size: font.px-to-rem(24px); | ||
} | ||
|
||
&__file { | ||
display: flex; | ||
flex-flow: column; | ||
row-gap: math.div(file-upload.$ods-file-upload-spacing, 2); | ||
|
||
&__info { | ||
display: grid; | ||
grid-template-columns: 1fr max-content max-content; | ||
column-gap: file-upload.$ods-file-upload-spacing; | ||
align-items: baseline; | ||
|
||
&__name { | ||
@include font.ellipsis(); | ||
} | ||
|
||
&__size { | ||
font-size: font.px-to-rem(12px); | ||
} | ||
} | ||
|
||
&__error { | ||
color: var(--ods-color-critical-500); | ||
font-size: font.px-to-rem(12px); | ||
font-weight: 600; | ||
} | ||
|
||
&__progress { | ||
display: grid; | ||
grid-template-columns: 1fr max-content; | ||
column-gap: file-upload.$ods-file-upload-spacing; | ||
align-items: center; | ||
font-size: font.px-to-rem(14px); | ||
font-weight: 600; | ||
|
||
&__bar { | ||
display: flex; | ||
|
||
&::part(progress) { | ||
width: 100%; | ||
} | ||
} | ||
} | ||
|
||
&__success { | ||
color: var(--ods-color-success-500); | ||
font-size: font.px-to-rem(12px); | ||
font-weight: 600; | ||
} | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
...s/src/components/file-upload/src/components/ods-file-upload-item/ods-file-upload-item.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { Component, type FunctionalComponent, Host, Prop, h } from '@stencil/core'; | ||
import { formatBytes } from '../../../../../utils/file'; | ||
import { ODS_BUTTON_SIZE, ODS_BUTTON_VARIANT } from '../../../../button/src'; | ||
import { ODS_ICON_NAME } from '../../../../icon/src'; | ||
|
||
@Component({ | ||
shadow: true, | ||
styleUrl: 'ods-file-upload-item.scss', | ||
tag: 'ods-file-upload-item', | ||
}) | ||
export class OdsFileUploadItem { | ||
@Prop({ reflect: false }) public cancelHandler!: () => void; | ||
@Prop({ reflect: true }) public error: string = ''; | ||
@Prop({ reflect: true }) public isDisabled: boolean = false; | ||
@Prop({ reflect: true }) public isUploaded: boolean = false; | ||
@Prop({ reflect: true }) public name!: string; | ||
@Prop({ reflect: true }) public progress?: number; | ||
@Prop({ reflect: true }) public size!: number; | ||
@Prop({ reflect: true }) public successLabel!: string; | ||
|
||
private renderStatus(): FunctionalComponent { | ||
if (this.error) { | ||
return ( | ||
<span class="ods-file-upload-item__file__error"> | ||
{ this.error } | ||
</span> | ||
); | ||
} | ||
|
||
if (this.progress && this.progress < 100) { | ||
return ( | ||
<div class="ods-file-upload-item__file__progress"> | ||
<ods-progress-bar | ||
class="ods-file-upload-item__file__progress__bar" | ||
max={ 100 } | ||
value={ this.progress }> | ||
</ods-progress-bar> | ||
|
||
<span> | ||
{ this.progress }% | ||
</span> | ||
</div> | ||
); | ||
} | ||
|
||
if (this.isUploaded) { | ||
return ( | ||
<span class="ods-file-upload-item__file__success"> | ||
<ods-icon name={ ODS_ICON_NAME.check }></ods-icon> { this.successLabel } | ||
</span> | ||
); | ||
} | ||
|
||
return <span></span>; | ||
} | ||
|
||
render(): FunctionalComponent { | ||
return ( | ||
<Host | ||
class={{ | ||
'ods-file-upload-item': true, | ||
'ods-file-upload-item--disabled': this.isDisabled, | ||
}}> | ||
<ods-icon | ||
class="ods-file-upload-item__icon" | ||
name={ ODS_ICON_NAME.file }> | ||
</ods-icon> | ||
|
||
<div class="ods-file-upload-item__file"> | ||
<div class="ods-file-upload-item__file__info"> | ||
<span class="ods-file-upload-item__file__info__name"> | ||
{ this.name } | ||
</span> | ||
|
||
<span class="ods-file-upload-item__file__info__size"> | ||
{ formatBytes(this.size) } | ||
</span> | ||
|
||
<ods-button | ||
icon={ ODS_ICON_NAME.cross } | ||
isDisabled={ this.isDisabled } | ||
label="" | ||
onClick={ () => this.cancelHandler() } | ||
size={ ODS_BUTTON_SIZE.sm } | ||
variant={ ODS_BUTTON_VARIANT.ghost }> | ||
</ods-button> | ||
</div> | ||
|
||
{ this.renderStatus() } | ||
</div> | ||
</Host> | ||
); | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
packages/ods/src/components/file-upload/src/components/ods-file-upload/ods-file-upload.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
@use 'sass:math'; | ||
@use '../../../../../style/font'; | ||
@use '../../../../../style/input'; | ||
|
||
$ods-file-upload-padding: 24px; | ||
$ods-file-upload-spacing: 8px; | ||
|
||
:host(.ods-file-upload) { | ||
display: inline-flex; | ||
flex-flow: column; | ||
row-gap: 8px; | ||
border: dashed 1px var(--ods-form-element-border-color-default); | ||
border-radius: 4px; | ||
overflow: hidden; | ||
color: var(--ods-color-text); | ||
} | ||
|
||
:host(.ods-file-upload--disabled) { | ||
@include input.ods-input-disabled(); | ||
|
||
.ods-file-upload__dropzone__icon { | ||
color: var(--ods-form-element-foreground-color-disabled); | ||
} | ||
} | ||
|
||
.ods-file-upload { | ||
&__dropzone { | ||
display: inline-flex; | ||
flex-flow: column; | ||
row-gap: $ods-file-upload-spacing; | ||
align-items: center; | ||
padding: $ods-file-upload-padding $ods-file-upload-padding 0; | ||
|
||
&--dragging { | ||
background-color: var(--ods-color-primary-100); | ||
} | ||
|
||
&--empty { | ||
padding: $ods-file-upload-padding; | ||
} | ||
|
||
&__input { | ||
display: none; | ||
} | ||
|
||
&__icon { | ||
color: var(--ods-color-primary-500); | ||
font-size: font.px-to-rem(32px); | ||
} | ||
|
||
&__file-format { | ||
font-size: font.px-to-rem(12px); | ||
} | ||
|
||
&__error { | ||
color: var(--ods-color-critical-500); | ||
font-size: font.px-to-rem(12px); | ||
font-weight: 600; | ||
} | ||
} | ||
|
||
&__list { | ||
display: flex; | ||
flex-flow: column; | ||
row-gap: math.div($ods-file-upload-spacing, 2); | ||
padding-bottom: $ods-file-upload-padding; | ||
} | ||
} |
Oops, something went wrong.