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

Milestone 2: Adding data-media-background prop #18

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
97 changes: 95 additions & 2 deletions vue/configurator/src/components/Configurator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,64 @@
v-model="prop.value"
size="large"
/>
<!-- data-media-background has a type of JSON string -->
<el-row
v-else-if="prop.type === WidgetPropType.INTERFACE"
class="prop-groupings"
>
<el-row v-for="(config, key) in prop.value" :key="key">
<!-- config needs to be confirmed as an object for it to have properties like 'type' since
it can be a string or boolean as defined in WidgetProps.ts -->
<!-- Placeholder uses "key" instead of config.name because config can be string | boolean | WidgetPropDefiniton -->
<el-input
v-if="
typeof config === 'object' &&
config?.type === WidgetPropType.STRING
"
v-model="config.value"
class="w-50 m-2"
:placeholder="key"
/>
<div
v-else-if="
typeof config === 'object' &&
config?.type === WidgetPropType.ARRAY
"
>
<label> colors example: red, blue </label>
<el-input
v-model="config.value"
class="w-50 m-2"
:placeholder="key"
/>
</div>
<el-select
v-else-if="
typeof config === 'object' &&
config?.type === WidgetPropType.ENUMERATION
"
v-model="config.value"
class="m-2"
placeholder="None"
size="small"
>
<el-option
v-for="item in config.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-checkbox
v-else-if="
typeof config === 'object' &&
config?.type === WidgetPropType.BOOLEAN
"
v-model="config.value"
size="large"
/>
</el-row>
</el-row>
</el-col>
</el-row>
</div>
Expand Down Expand Up @@ -192,6 +250,29 @@ export interface ConfiguratorDefinition {
if (prop.type === WidgetPropType.STRING) {
value = value.toString().trim();
}
// If prop is an JSON object, extact the value to use to populate the attribute.
// Convert the object to a JSON string object as defined
// https://docs.manifold.xyz/v/manifold-for-developers/resources/widgets/marketplace-widgets/widgets/data-attributes#data-media-background
if (prop.type === WidgetPropType.INTERFACE) {
const propObjectValue = Object.fromEntries(
Object.entries(value).map(([k, v]) => {
if (v.type === WidgetPropType.ARRAY) {
// Splitting colors given into an array of colors. If user ends string with a "," the empty element is removed
// Make sure to not split by commas that are contained in RGB(A)/HSL(A) CSS values.
return [
k,
v.value.includes("rgb") || v.value.includes("hsl")
? v.value.split(/,(?![^()]*\))/)
: v.value.endsWith(",")
? v.value.slice(0, -1).split(",")
: v.value.split(","),
];
}
return [k, v.value];
})
);
value = JSON.stringify(propObjectValue);
}
if (value !== prop.defaultValue) {
// only change if it's different
if (value !== element.getAttribute(propKey)) {
Expand Down Expand Up @@ -297,7 +378,15 @@ export default class Configurator extends Vue {
margin-top: 20px;
margin-bottom: 10px;
}

.prop-groupings {
align-items: center;
border-color: lightgrey;
border-style: solid;
border-width: thin;
border-radius: 5px;
height: 150px;
width: 250px;
}
.code-blocks {
text-align: left;
}
Expand All @@ -308,7 +397,6 @@ export default class Configurator extends Vue {
.code-blocks h2 {
margin-top: 5px;
}

.widget-configuration {
text-align: left;
}
Expand All @@ -321,4 +409,9 @@ export default class Configurator extends Vue {
word-wrap: break-word;
overflow: auto;
}
label {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor comment: if anyone were to add a label element to the configurator, it would be styled using the rules below.

font-size: 12px;
margin-bottom: 20px;
color: rgba(97, 91, 91, 0.521);
}
</style>
21 changes: 19 additions & 2 deletions vue/configurator/src/components/lib/WidgetProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@ export enum WidgetPropType {
STRING = "string",
BOOLEAN = "boolean",
ENUMERATION = "enumeration",
INTERFACE = "interface",
ARRAY = "array",
}

export interface MediaBackgroundConfig {
jaxonL marked this conversation as resolved.
Show resolved Hide resolved
/** angle in degrees representing from which direction the gradient (linear/conic) flows */
// Number
angle?: WidgetPropDefinition;
/** string array of colors for the media background */
// string[]
colors?: WidgetPropDefinition;
/** URI to the background image. takes precedence over the background color/gradient */
// string
image?: WidgetPropDefinition;
/** if two or more color values are provided, specifies the type of background */
// enumeration of "linear" | "conic" | "radial"
type?: WidgetPropDefinition;
}

interface WidgetPropOptions {
Expand All @@ -12,8 +29,8 @@ interface WidgetPropOptions {
export interface WidgetPropDefinition {
name: string;
type: WidgetPropType;
value: string | boolean;
defaultValue: string | boolean;
value: string | boolean | MediaBackgroundConfig;
defaultValue: string | boolean | MediaBackgroundConfig;
options?: WidgetPropOptions[];
required?: boolean;
dependentProps?: string[];
Expand Down
45 changes: 45 additions & 0 deletions vue/configurator/src/views/MarketplaceView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,51 @@ export default class MarketplaceView extends Vue {
defaultValue: "",
required: false,
},
"data-media-background": {
name: "Background Media",
type: WidgetPropType.INTERFACE,
value: {
angle: {
name: "angle",
type: WidgetPropType.STRING,
value: "",
defaultValue: "",
},
colors: {
name: "colors",
type: WidgetPropType.ARRAY,
value: "",
defaultValue: [],
},
image: {
name: "image",
type: WidgetPropType.STRING,
value: "",
defaultValue: "",
},
type: {
name: "type",
type: WidgetPropType.ENUMERATION,
value: "",
options: [
{
value: "linear",
label: "Linear",
},
{
value: "conic",
label: "Conic",
},
{
value: "radial",
label: "Radial",
},
],
},
},
defaultValue: {},
required: false,
},
},
},
],
Expand Down