diff --git a/vue/configurator/src/components/Configurator.vue b/vue/configurator/src/components/Configurator.vue index 1aff76f..347f23d 100644 --- a/vue/configurator/src/components/Configurator.vue +++ b/vue/configurator/src/components/Configurator.vue @@ -68,6 +68,64 @@ v-model="prop.value" size="large" /> + + + + + + +
+ + +
+ + + + +
+
@@ -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)) { @@ -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; } @@ -308,7 +397,6 @@ export default class Configurator extends Vue { .code-blocks h2 { margin-top: 5px; } - .widget-configuration { text-align: left; } @@ -321,4 +409,9 @@ export default class Configurator extends Vue { word-wrap: break-word; overflow: auto; } +label { + font-size: 12px; + margin-bottom: 20px; + color: rgba(97, 91, 91, 0.521); +} diff --git a/vue/configurator/src/components/lib/WidgetProps.ts b/vue/configurator/src/components/lib/WidgetProps.ts index b7c214c..5057ca9 100644 --- a/vue/configurator/src/components/lib/WidgetProps.ts +++ b/vue/configurator/src/components/lib/WidgetProps.ts @@ -2,6 +2,23 @@ export enum WidgetPropType { STRING = "string", BOOLEAN = "boolean", ENUMERATION = "enumeration", + INTERFACE = "interface", + ARRAY = "array", +} + +export interface MediaBackgroundConfig { + /** 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 { @@ -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[]; diff --git a/vue/configurator/src/views/MarketplaceView.vue b/vue/configurator/src/views/MarketplaceView.vue index da24da9..e7a549c 100644 --- a/vue/configurator/src/views/MarketplaceView.vue +++ b/vue/configurator/src/views/MarketplaceView.vue @@ -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, + }, }, }, ],