Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(file-preview-cards): add preview card/cards #2289

Open
wants to merge 2 commits into
base: 2207-file-input
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions .changeset/cool-zebras-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ebay/ebayui-core": minor
---

Add ebay-file-preview-card and ebay-file-preview-card-group
52 changes: 52 additions & 0 deletions src/components/ebay-file-input/examples/with-mock-uploads.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { FileInputEvent } from "../component-browser";

static async function mockFetch() {
await new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
return `https://fakeurl.com/${Math.random().toString(36).substring(7)}`;
}

class {
declare state: {
files: [File, string | undefined][];
};

onCreate() {
this.state = {
files: [],
};
}

handleInput({ files }: FileInputEvent) {
const fileList = Array.from(files);
this.state.files = this.state.files.concat(fileList.map((file) => [file, undefined]));
for (const file of fileList) {
mockFetch().then((url) => {
const index = this.state.files.findIndex(([f]) => f === file);
this.state.files = [
...this.state.files.slice(0, index),
[file, url],
...this.state.files.slice(index + 1)
];
})
}
}

handleDelete(index: number) {
this.state.files = [
...this.state.files.slice(0, index),
...this.state.files.slice(index + 1)
];
}
}
<ebay-file-input multiple on-input("handleInput") ...input>
<@header class="subtitleClass" id="subtitleId">
<p>Multiple files</p>
</@header>
<span>Browse files</span>
</ebay-file-input>

<ebay-file-preview-card-group on-delete("handleDelete") on-cancel("handleDelete")>
<for|[file, url]| of=state.files>
<@card file=file status=url ? undefined : "uploading"/>
</for>
</ebay-file-preview-card-group>
35 changes: 35 additions & 0 deletions src/components/ebay-file-input/examples/with-preview-cards.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { FileInputEvent } from "../component-browser";
class {
declare state: {
files: File[];
};

onCreate() {
this.state = {
files: [],
};
}

handleInput({ files }: FileInputEvent) {
this.state.files = this.state.files.concat(Array.from(files));
}

handleDelete(index: number) {
this.state.files = [
...this.state.files.slice(0, index),
...this.state.files.slice(index + 1)
];
}
}
<ebay-file-input multiple on-input("handleInput") ...input>
<@header class="subtitleClass" id="subtitleId">
<p>Multiple files</p>
</@header>
<span>Browse files</span>
</ebay-file-input>

<ebay-file-preview-card-group on-delete("handleDelete") on-cancel("handleDelete")>
<for|file| of=state.files>
<@card file=file/>
</for>
</ebay-file-preview-card-group>
29 changes: 29 additions & 0 deletions src/components/ebay-file-input/file-input.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import Readme from "./README.md";
import component from "./index.marko";
import DefaultTemplate from "./examples/default.marko";
import DefaultCode from "./examples/default.marko?raw";
import WithPreviewCardsTemplate from "./examples/with-preview-cards.marko";
import WithPreviewCardsCode from "./examples/with-preview-cards.marko?raw";
import WithMockUploadsTemplate from "./examples/with-mock-uploads.marko";
import WithMockUploadsCode from "./examples/with-mock-uploads.marko?raw";

const Template = (args) => ({
input: addRenderBodies(args),
Expand Down Expand Up @@ -67,3 +71,28 @@ Default.parameters = {
},
};

export const WithPreviewCards = (args) => ({
input: args,
component: WithPreviewCardsTemplate,
});
WithPreviewCards.args = {};
WithPreviewCards.parameters = {
docs: {
source: {
code: WithPreviewCardsCode,
},
},
};

export const WithMockUploads = (args) => ({
input: args,
component: WithMockUploadsTemplate,
});
WithMockUploads.args = {};
WithMockUploads.parameters = {
docs: {
source: {
code: WithMockUploadsCode,
},
},
};
16 changes: 16 additions & 0 deletions src/components/ebay-file-preview-card-group/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h1 style='display: flex; justify-content: space-between; align-items: center;'>
<span>
ebay-file-preview-card
</span>
<span style='font-weight: normal; font-size: medium; margin-bottom: -15px;'>
DS v2.1.0
</span>
</h1>

Group of file preview cards, primarily used alongside `ebay-file-input`.

## Examples and Documentation

- [Storybook](https://ebay.github.io/ebayui-core/?path=/story/media-ebay-file-preview-card-group)
- [Storybook Docs](https://ebay.github.io/ebayui-core/?path=/docs/media-ebay-file-preview-card-group)
- [Code Examples](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-file-preview-card-group/examples)
36 changes: 36 additions & 0 deletions src/components/ebay-file-preview-card-group/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { WithNormalizedProps } from "../../global";
import type {
FilePreviewCardEvent,
Input as FilePreviewCardInput,
} from "../ebay-file-preview-card/component";

interface FilePreviewCardGroupInput {
card?: Marko.RepeatableAttrTag<FilePreviewCardInput>;
"a11y-cancel-upload-text"?: FilePreviewCardInput["a11y-cancel-upload-text"];
"delete-text"?: FilePreviewCardInput["delete-text"];
"menu-actions"?: FilePreviewCardInput["menu-actions"];
"a11y-show-more-text"?: FilePreviewCardInput["a11y-show-more-text"];
"on-menu-action"?: (index: number, event: FilePreviewCardEvent) => void;
"on-delete"?: (index: number) => void;
"on-cancel"?: (index: number) => void;
}

export type Input = WithNormalizedProps<FilePreviewCardGroupInput>;

export interface State {
showing: number;
}

const SHOW_AMOUNT = 15;

class FilePreviewCardGroup extends Marko.Component<Input, State> {
onCreate() {
this.state = { showing: SHOW_AMOUNT };
}

showMore() {
this.state.showing += SHOW_AMOUNT;
}
}

export default FilePreviewCardGroup;
21 changes: 21 additions & 0 deletions src/components/ebay-file-preview-card-group/examples/default.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
$ const files = [
{
name: "file-name.jpg",
type: "image/jpeg",
src: "https://ir.ebaystatic.com/cr/v/c01/skin/docs/tb-real-square-pic.jpg",
},
{
name: "file-name.jpg",
type: "image/jpeg",
src: "https://ir.ebaystatic.com/cr/v/c01/skin/docs/tb-real-square-pic.jpg",
},
];
<ebay-file-preview-card
a11y-cancel-upload-text="cancel upload"
delete-text="remove"
a11y-show-more-text="show more"
>
<for|file| of=files>
<@card file=file/>
</for>
</ebay-file-preview-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { tagToString } from "../../../.storybook/storybook-code-source";
import { addRenderBodies } from "../../../.storybook/utils";
import Readme from "./README.md";
import component from "./index.marko";

const Template = (args) => ({
input: addRenderBodies(args),
});

export default {
title: "media/ebay-file-preview-card-group",
component,
parameters: {
docs: {
description: {
component: Readme,
},
},
},
argTypes: {
card: {
name: "@card",
table: {
category: "@attribute tags",
},
description:
"A repeatable attribute tag for each file preview card",
},
a11yCancelUploadText: {
type: "string",
control: { type: "text" },
description:
"a11y text for cancel upload button, applied to all cards",
},
deleteText: {
type: "string",
control: { type: "text" },
description: "Text for delete button, applied to all cards",
},
menuActions: {
type: "array",
description: "List of menu actions, applied to all cards",
control: { type: "object" },
},
a11yShowMoreText: {
type: "string",
control: { type: "text" },
description: "a11y text for show more button, applied to all cards",
},
"onMenu-action": {
action: "on-menu-action",
description:
"Triggered when an action is selected from the menu on a card",
table: {
category: "Events",
defaultValue: {
summary:
"index, eventName, event /* from ebay-menu-button */",
},
},
},
onDelete: {
action: "on-delete",
description:
"Triggered when the delete button is clicked on a card",
table: {
category: "Events",
defaultValue: {
summary: "index",
},
},
},
onCancel: {
action: "on-cancel",
description:
"Triggered when the cancel button is clicked on a card",
table: {
category: "Events",
defaultValue: {
summary: "index",
},
},
},
},
};

const frogImage = {
name: "frog.jpg",
type: "image/jpeg",
src: "https://ir.ebaystatic.com/cr/v/c01/skin/docs/tb-real-square-pic.jpg",
};

export const Default = Template.bind({});
Default.args = {
a11yCancelUploadText: "Cancel upload",
deleteText: "Delete",
card: [
{
file: { ...frogImage },
},
{
file: { ...frogImage },
},
{
file: { ...frogImage },
},
],
};

export const ManyCards = Template.bind({});
ManyCards.args = {
a11yCancelUploadText: "Cancel upload",
deleteText: "Delete",
card: [...Array(35)].map(() => ({
file: { ...frogImage },
})),
};
33 changes: 33 additions & 0 deletions src/components/ebay-file-preview-card-group/index.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
$ const { card = [], a11yCancelUploadText, deleteText, menuActions, a11yShowMoreText } = input;
$ const cards = [...card];
$ const notShowing = cards.length - state.showing;

<div class="file-preview-card-group">
<ul>
<for|i| from=0 to=(notShowing > 0 ? state.showing : cards.length) - 1>
$ const cardInput = cards[i];
<li>
<ebay-file-preview-card
a11y-cancel-upload-text=a11yCancelUploadText
delete-text=deleteText
menu-actions=menuActions
...cardInput
on-cancel("emit", "cancel", i)
on-delete("emit", "delete", i)
on-menu-action("emit", "menu-action", i)
/>
</li>
</for>
<if(notShowing > 0)>
<li>
<ebay-file-preview-card
file=cards[state.showing].file
show-more=notShowing
a11y-show-more-text=a11yShowMoreText
on-show-more("showMore")
on-delete("emit", "delete", state.showing)
/>
</li>
</if>
</ul>
</div>
1 change: 1 addition & 0 deletions src/components/ebay-file-preview-card-group/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "@ebay/skin/file-preview-card-group";
16 changes: 16 additions & 0 deletions src/components/ebay-file-preview-card/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h1 style='display: flex; justify-content: space-between; align-items: center;'>
<span>
ebay-file-preview-card
</span>
<span style='font-weight: normal; font-size: medium; margin-bottom: -15px;'>
DS v2.1.0
</span>
</h1>

Preview card for files, primarily used alongside `ebay-file-preview-card-group` and `ebay-file-input`.

## Examples and Documentation

- [Storybook](https://ebay.github.io/ebayui-core/?path=/story/media-ebay-file-preview-card)
- [Storybook Docs](https://ebay.github.io/ebayui-core/?path=/docs/media-ebay-file-preview-card)
- [Code Examples](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-file-preview-card/examples)
Loading
Loading