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
94 changes: 94 additions & 0 deletions vue/configurator/src/components/Configurator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,72 @@
v-model="prop.value"
size="large"
/>
<!-- data-media-background has a type of JSON string -->
<el-row
v-else-if="prop.type === WidgetPropType.INTERFACE"
style="
align-items: center;
border-color: lightgrey;
border-style: solid;
border-width: thin;
border-radius: 5px;
height: 150px;
width: 250px;
jaxonL marked this conversation as resolved.
Show resolved Hide resolved
"
>
<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 id="multipleInputs"> colors example: red, blue </label>
Copy link
Contributor

@jaxonL jaxonL Apr 13, 2023

Choose a reason for hiding this comment

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

just caught this this time around -- if there are more config props with type = ARRAY, you would have multiple labels with the same id + placeholder test. that wouldn't be good for accessibility issues.

Copy link
Author

Choose a reason for hiding this comment

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

true! I actually decided I didn't need to ID this label since any labels created by config props with type = ARRAY would then be styled using the selector label rather than creating accessibility issues by potentially using same ids

<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 +258,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 @@ -321,4 +410,9 @@ export default class Configurator extends Vue {
word-wrap: break-word;
overflow: auto;
}
label[id="multipleInputs"] {
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
46 changes: 46 additions & 0 deletions vue/configurator/src/views/MarketplaceView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,52 @@ 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,
// Testing with hard coded values
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