Skip to content

Commit

Permalink
extract License Terms List to separate component
Browse files Browse the repository at this point in the history
  • Loading branch information
samfairbairn committed May 10, 2024
1 parent 5c30350 commit ce7af79
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 141 deletions.
2 changes: 1 addition & 1 deletion examples/next-app/components/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { IpProvider, useIpContext, IpWidget, IpPolicyAccordion, IpRoyaltyPieChart, IpGraph, Button } from "@storyprotocol/storykit"
import { IpProvider, useIpContext, IpWidget, IpPolicyAccordion, IpRoyaltyPieChart, IpGraph } from "@storyprotocol/storykit"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import React from "react"

Expand Down
2 changes: 1 addition & 1 deletion packages/storykit/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@storyprotocol/storykit",
"author": "storyprotocol engineering <eng@storyprotocol.xyz>",
"version": "0.1.8",
"version": "0.1.9",
"type": "module",
"exports": {
".": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,13 @@
import { POLICY_TYPE } from "@/lib/types"
import { cn, getPolicyTypeByPILData } from "@/lib/utils"
import { useIpContext } from "@/providers"
import { cva } from "class-variance-authority"
import { CircleCheck, CircleMinus } from "lucide-react"
import { useState } from "react"
import { FaCaretDown, FaCaretUp } from "react-icons/fa6"

import "../../global.css"
import LicenseTerms from "../LicenseTerms/LicenseTerms"
import "./styles.css"

const CANS = {
REMIX: "Remix this work",
INCLUDE: "Include this work in their own work(s)",
CREDIT: "Credit you appropriately",
DISTRIBUTE: "Distribute their remix anywhere",
PURCHASE_RIGHTS: "Purchase the right to use your creation (for a price you set) and register it into Story Protocol",
CREATOR_CREDIT: "Credit you as the creator",
PUBLISH: "Display / publish the work in any medium",
}

const ShowCans = ({ type }: { type: string }) => {
switch (type) {
case POLICY_TYPE.NON_COMMERCIAL_SOCIAL_REMIXING:
return [CANS.REMIX, CANS.INCLUDE, CANS.CREDIT, CANS.DISTRIBUTE]
break
case POLICY_TYPE.COMMERCIAL_USE:
return [CANS.PURCHASE_RIGHTS, CANS.CREATOR_CREDIT, CANS.PUBLISH]
break
case POLICY_TYPE.COMMERCIAL_REMIX:
return [CANS.REMIX, CANS.INCLUDE, CANS.CREDIT, CANS.DISTRIBUTE]
break
case POLICY_TYPE.OPEN_DOMAIN:
return [CANS.REMIX, CANS.INCLUDE, CANS.DISTRIBUTE, CANS.PUBLISH]
break
default:
return []
break
}
}

const CANNOTS = {
RESELL: "Resell your original work",
COMMERCIALIZE: "Commercialize the remix",
CLAIM_AS_ORIGINAL: "Claim credit for the remix (as original work)",
CLAIM: "Claim your work as their own",
REMIX: "Create remixes of the commercial use.",
}

const ShowCannots = ({ type }: { type: string }) => {
switch (type) {
case POLICY_TYPE.NON_COMMERCIAL_SOCIAL_REMIXING:
return [CANNOTS.RESELL, CANNOTS.COMMERCIALIZE, CANNOTS.CLAIM_AS_ORIGINAL]
break
case POLICY_TYPE.COMMERCIAL_USE:
return [CANNOTS.CLAIM, CANNOTS.REMIX, CANNOTS.RESELL]
break
case POLICY_TYPE.COMMERCIAL_REMIX:
return [CANNOTS.RESELL, CANNOTS.COMMERCIALIZE, CANNOTS.CLAIM_AS_ORIGINAL]
break
case POLICY_TYPE.OPEN_DOMAIN:
return [CANNOTS.RESELL, CANNOTS.COMMERCIALIZE, CANNOTS.CLAIM_AS_ORIGINAL, CANNOTS.CLAIM]
break
default:
return [CANNOTS.RESELL, CANNOTS.CLAIM, CANNOTS.REMIX]
break
}
}

const policiesStyles = cva("", {
variants: {
size: {
Expand All @@ -85,8 +26,6 @@ function IpPolicyAccordion({ size = "medium" }: IpPolicyAccordionProps) {
const { policyData } = useIpContext()
const [expanded, setExpanded] = useState<number | null>(0)

const iconWidth = size === "small" ? 16 : size === "medium" ? 20 : 24

return policyData?.length ? (
<div className={cn("skIpPolicyAccordion", policiesStyles({ size }))}>
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
Expand All @@ -106,30 +45,7 @@ function IpPolicyAccordion({ size = "medium" }: IpPolicyAccordionProps) {
expanded === index && "skIpPolicyAccordion__item-list--expanded"
)}
>
<div className="skIpPolicyAccordion__properties">
{ShowCans({ type: getPolicyTypeByPILData(policy.licenseTerms) }).length ? (
<>
<div className="skIpPolicyAccordion__item-list-title">Others Can</div>
<div className="skIpPolicyAccordion__list">
{ShowCans({ type: getPolicyTypeByPILData(policy.licenseTerms) }).map((can, index) => (
<div key={index} className="skIpPolicyAccordion__property skIpPolicyAccordion__property--can">
<CircleCheck width={iconWidth} />
<span>{can}</span>
</div>
))}
</div>
</>
) : null}
<div className="skIpPolicyAccordion__item-list-title">Others Cannot</div>
<div className="skIpPolicyAccordion__list">
{ShowCannots({ type: getPolicyTypeByPILData(policy.licenseTerms) }).map((can, index) => (
<div key={index} className="skIpPolicyAccordion__property skIpPolicyAccordion__property--cannot">
<CircleMinus width={iconWidth} />
<span>{can}</span>
</div>
))}
</div>
</div>
<LicenseTerms size={size} type={getPolicyTypeByPILData(policy.licenseTerms)} />
</div>

{index < policyData.length - 1 && <div className="skIpPolicyAccordion__divider" />}
Expand Down
45 changes: 1 addition & 44 deletions packages/storykit/src/components/IpPolicyAccordion/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,60 +10,17 @@
}

.skIpPolicyAccordion__item-list {
@apply flex w-full items-center justify-between overflow-hidden h-0;
@apply flex w-full overflow-hidden h-0;

&.skIpPolicyAccordion__item-list--expanded {
@apply h-auto;
}
}

.skIpPolicyAccordion__properties {
@apply flex flex-col pt-2 gap-2;
}

.skIpPolicyAccordion__item-list-title {
@apply font-bold;
}

.skIpPolicyAccordion__list {
@apply flex flex-col;
}

.skIpPolicyAccordion__property {
@apply flex w-full items-center gap-2;

&.skIpPolicyAccordion__property--can > svg {
@apply text-green-500;
}

&.skIpPolicyAccordion__property--cannot > svg {
@apply text-red-500;
}
}

.skIpPolicyAccordion__divider {
@apply border-b border-gray-200 w-full my-2;
}

&.skIpPolicyAccordion--small {
@apply text-sm;
}

&.skIpPolicyAccordion--medium {
@apply text-base;

.policy-list {
@apply gap-1;
}
}

&.skIpPolicyAccordion--large {
@apply text-lg;
.policy-list {
@apply gap-2;
}
}

&.skIpPolicyAccordion--no-policy {
@apply text-slate-400;
}
Expand Down
115 changes: 115 additions & 0 deletions packages/storykit/src/components/LicenseTerms/LicenseTerms.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { POLICY_TYPE, PolicyType } from "@/lib/types"
import { cn } from "@/lib/utils"
import { cva } from "class-variance-authority"
import { CircleCheck, CircleMinus } from "lucide-react"

import "../../global.css"
import "./styles.css"

const CANS = {
REMIX: "Remix this work",
INCLUDE: "Include this work in their own work(s)",
CREDIT: "Credit you appropriately",
DISTRIBUTE: "Distribute their remix anywhere",
PURCHASE_RIGHTS: "Purchase the right to use your creation (for a price you set) and register it into Story Protocol",
CREATOR_CREDIT: "Credit you as the creator",
PUBLISH: "Display / publish the work in any medium",
}

const ShowCans = ({ type }: { type: string }) => {
switch (type) {
case POLICY_TYPE.NON_COMMERCIAL_SOCIAL_REMIXING:
return [CANS.REMIX, CANS.INCLUDE, CANS.CREDIT, CANS.DISTRIBUTE]
break
case POLICY_TYPE.COMMERCIAL_USE:
return [CANS.PURCHASE_RIGHTS, CANS.CREATOR_CREDIT, CANS.PUBLISH]
break
case POLICY_TYPE.COMMERCIAL_REMIX:
return [CANS.REMIX, CANS.INCLUDE, CANS.CREDIT, CANS.DISTRIBUTE]
break
case POLICY_TYPE.OPEN_DOMAIN:
return [CANS.REMIX, CANS.INCLUDE, CANS.DISTRIBUTE, CANS.PUBLISH]
break
default:
return []
break
}
}

const CANNOTS = {
RESELL: "Resell your original work",
COMMERCIALIZE: "Commercialize the remix",
CLAIM_AS_ORIGINAL: "Claim credit for the remix (as original work)",
CLAIM: "Claim your work as their own",
REMIX: "Create remixes of the commercial use.",
}

const ShowCannots = ({ type }: { type: string }) => {
switch (type) {
case POLICY_TYPE.NON_COMMERCIAL_SOCIAL_REMIXING:
return [CANNOTS.RESELL, CANNOTS.COMMERCIALIZE, CANNOTS.CLAIM_AS_ORIGINAL]
break
case POLICY_TYPE.COMMERCIAL_USE:
return [CANNOTS.CLAIM, CANNOTS.REMIX, CANNOTS.RESELL]
break
case POLICY_TYPE.COMMERCIAL_REMIX:
return [CANNOTS.RESELL, CANNOTS.COMMERCIALIZE, CANNOTS.CLAIM_AS_ORIGINAL]
break
case POLICY_TYPE.OPEN_DOMAIN:
return [CANNOTS.RESELL, CANNOTS.COMMERCIALIZE, CANNOTS.CLAIM_AS_ORIGINAL, CANNOTS.CLAIM]
break
default:
return [CANNOTS.RESELL, CANNOTS.CLAIM, CANNOTS.REMIX]
break
}
}

const policiesStyles = cva("", {
variants: {
size: {
small: "skLicenseTerms--small",
medium: "skLicenseTerms--medium",
large: "skLicenseTerms--large",
},
},
})

export type LicenseTermsProps = {
size?: "small" | "medium" | "large"
type: PolicyType
}

function LicenseTerms({ size = "medium", type }: LicenseTermsProps) {
const iconWidth = size === "small" ? 16 : size === "medium" ? 20 : 24

return (
<div className={cn("skLicenseTerms", policiesStyles({ size }))}>
<div className="skLicenseTerms__properties">
{ShowCans({ type }).length ? (
<>
<div className="skLicenseTerms__item-list-title">Others Can</div>
<div className="skLicenseTerms__list">
{ShowCans({ type }).map((can, index) => (
<div key={index} className="skLicenseTerms__property skLicenseTerms__property--can">
<CircleCheck width={iconWidth} />
<span>{can}</span>
</div>
))}
</div>
</>
) : null}
<div className="skLicenseTerms__item-list-title">Others Cannot</div>
<div className="skLicenseTerms__list">
{ShowCannots({ type }).map((can, index) => (
<div key={index} className="skLicenseTerms__property skLicenseTerms__property--cannot">
<CircleMinus width={iconWidth} />
<span>{can}</span>
</div>
))}
</div>
</div>
</div>
)
}

export default LicenseTerms
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Canvas, Controls, Meta } from "@storybook/blocks"

import * as LicenseTermsStory from "./LicenseTerms.stories"

<Meta of={LicenseTermsStory} />

# LicenseTerms

Displays the License Terms cans and cannots for specified license type.

#### Example

<Canvas of={LicenseTermsStory.Select} />

<Controls />

## Usage

```ts

import { LicenseTerms, POLICY_TYPE } from "@storyprotocol/storykit"

const ExamplePage = () => {
return (
<LicenseTerms type={POLICY_TYPE.NON_COMMERCIAL_SOCIAL_REMIXING} />
);
};

export default ExamplePage;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { POLICY_TYPE, PolicyType } from "@/index"
import type { Meta, StoryObj } from "@storybook/react"

import Example from "../LicenseTerms"

const meta = {
title: "UI/LicenseTerms",
component: Example,
parameters: {
layout: "centered",
},
argTypes: {
type: {
options: Object.values(POLICY_TYPE),
},
},
args: {},
} satisfies Meta<typeof Example>

export default meta
type Story = StoryObj<typeof meta>

export const Select: Story = {
argTypes: {},
args: {
size: "medium",
type: POLICY_TYPE.COMMERCIAL_REMIX as PolicyType,
},
}
1 change: 1 addition & 0 deletions packages/storykit/src/components/LicenseTerms/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as LicenseTerms } from "./LicenseTerms"
Loading

0 comments on commit ce7af79

Please sign in to comment.