diff --git a/components/viewer/ViewProjectRow.vue b/components/viewer/ViewProjectRow.vue
index 5f28eea..7400815 100644
--- a/components/viewer/ViewProjectRow.vue
+++ b/components/viewer/ViewProjectRow.vue
@@ -33,7 +33,7 @@
diff --git a/components/viewer/StyleRow.vue b/components/viewer/style/StyleRow.vue
similarity index 100%
rename from components/viewer/StyleRow.vue
rename to components/viewer/style/StyleRow.vue
diff --git a/components/viewer/style/engine.ts b/components/viewer/style/engine.ts
new file mode 100644
index 0000000..a98a16c
--- /dev/null
+++ b/components/viewer/style/engine.ts
@@ -0,0 +1,126 @@
+import Handlebars from 'handlebars';
+import { join, map } from 'ramda';
+
+import { ObjStyles, ProjectStyles, RowStyles } from '~/composables/project';
+
+export abstract class StyleGenerator {
+ abstract name: string;
+ abstract gen(styling: T): string;
+}
+
+export function createStyles(
+ styling: T,
+ generators: StyleGenerator[],
+): string {
+ const styles = map((generator) => generator.gen(styling).trim(), generators);
+ console.log('Generated Styles', styles);
+ return join('\n', styles);
+}
+
+export class ProjectStylesGen extends StyleGenerator {
+ name = 'project';
+
+ private readonly _template;
+ constructor() {
+ super();
+ this._template = Handlebars.compile(ProjectStylesGen.TEMPLATE);
+ }
+
+ gen(styling: ProjectStyles): string {
+ return this._template(styling);
+ }
+
+ static TEMPLATE: string = `
+ .project {
+ background-color: {{backgroundColor}};
+ }
+ `;
+}
+
+export class RowStylesGen extends StyleGenerator {
+ name = 'row';
+
+ private readonly _template;
+ constructor() {
+ super();
+ this._template = Handlebars.compile(RowStylesGen.TEMPLATE);
+ }
+
+ gen(styling: ObjStyles): string {
+ return this._template(styling);
+ }
+
+ static TEMPLATE: string = `
+ .project-row {
+ {{#if rowBgColorIsOn}}
+ background-color: {{rowBgColor}};
+ {{/if}}
+
+ color: {{rowTextColor}};
+ .row-title {
+ color: {{rowTitleColor}};
+ }
+ }
+ `;
+}
+
+export class ObjStylesGen extends StyleGenerator {
+ name = 'obj';
+
+ private readonly _template;
+ constructor() {
+ super();
+ this._template = Handlebars.compile(ObjStylesGen.TEMPLATE);
+ }
+
+ gen(styling: ObjStyles): string {
+ // Ugly Hack but the origina format is cursed
+ const computed = {
+ objectBorderRadiusUnit: styling.objectBorderRadiusIsPixels ? 'px' : '%',
+ objectBorderRadiusTopLeft:
+ Number.parseFloat(styling.objectBorderRadiusTopLeft) * 10,
+ objectBorderRadiusTopRight:
+ Number.parseFloat(styling.objectBorderRadiusTopRight) * 10,
+ objectBorderRadiusBottomLeft:
+ Number.parseFloat(styling.objectBorderRadiusBottomLeft) * 10,
+ objectBorderRadiusBottomRight:
+ Number.parseFloat(styling.objectBorderRadiusBottomRight) * 10,
+ };
+ return this._template({ ...styling, ...computed });
+ }
+
+ static TEMPLATE: string = `
+ .project-obj {
+ {{#if objectBgColorIsOn}}
+ background-color: {{objectBgColor}};
+ {{/if}}
+
+ color: {{objectTextColor}};
+ .object-title {
+ color: {{objectTitleColor}};
+ }
+
+ {{#if objectBorderIsOn}}
+ border-color: {{objectBorderColor}};
+ border-style: {{objectBorderStyle}};
+ border-width: {{objectBorderWidth}}px;
+
+ border-top-left-radius: {{objectBorderRadiusTopLeft}}{{objectBorderRadiusUnit}};
+ border-top-right-radius: {{objectBorderRadiusTopRight}}{{objectBorderRadiusUnit}};
+ border-bottom-left-radius: {{objectBorderRadiusBottomLeft}}{{objectBorderRadiusUnit}};
+ border-bottom-right-radius: {{objectBorderRadiusBottomRight}}{{objectBorderRadiusUnit}};
+ {{/if}}
+
+ {{#if selBgColorIsOn}}
+ &.selected {
+ background-color: {{selFilterBgColor}}
+ }
+ {{/if}}
+ {{#if reqBgColorIsOn}}
+ &.disabled {
+ background-color: {{reqFilterBgColor}}
+ }
+ {{/if}}
+ }
+ `;
+}
diff --git a/composables/project.ts b/composables/project.ts
index 3035114..0735cf5 100644
--- a/composables/project.ts
+++ b/composables/project.ts
@@ -6,6 +6,28 @@ export type AddonStyles = {
export type ObjStyles = {
objectTitle: string;
objectText: string;
+
+ objectTitleColor: string;
+ objectTextColor: string;
+
+ objectBgColorIsOn: boolean;
+ objectBgColor: string;
+
+ objectBorderIsOn: boolean;
+ objectBorderColor: string;
+ objectBorderStyle: string;
+ objectBorderWidth: number;
+ objectBorderRadiusTopLeft: string;
+ objectBorderRadiusTopRight: string;
+ objectBorderRadiusBottomRight: string;
+ objectBorderRadiusBottomLeft: string;
+ objectBorderRadiusIsPixels: boolean;
+
+ selBgColorIsOn: boolean;
+ selFilterBgColor: string;
+
+ reqBgColorIsOn: boolean;
+ reqFilterBgColor: string;
};
export type RowStyles = ObjStyles &
diff --git a/package.json b/package.json
index 0e9cad3..893cea3 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"@vueuse/core": "^10.7.2",
"@vueuse/nuxt": "^10.7.2",
"bootstrap": "5.3.*",
+ "handlebars": "^4.7.8",
"perfect-debounce": "^1.0.0",
"pinia": "^2.1.6",
"ramda": "^0.29.0",
diff --git a/pages/index.vue b/pages/index.vue
index 04a6222..6e7319b 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -75,7 +75,7 @@
import { ref } from '#imports';
import ViewBackpack from '~/components/viewer/modal/ViewBackpack.vue';
import ViewSearch from '~/components/viewer/modal/ViewSearch.vue';
-import StyleProject from '~/components/viewer/StyleProject.vue';
+import StyleProject from '~/components/viewer/style/StyleProject.vue';
import ViewMenuBar from '~/components/viewer/ViewMenuBar.vue';
import { useProjectRefs, useProjectStore } from '~/composables/store/project';
diff --git a/yarn.lock b/yarn.lock
index 959e7e7..2a7764e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6454,6 +6454,24 @@ __metadata:
languageName: node
linkType: hard
+"handlebars@npm:^4.7.8":
+ version: 4.7.8
+ resolution: "handlebars@npm:4.7.8"
+ dependencies:
+ minimist: ^1.2.5
+ neo-async: ^2.6.2
+ source-map: ^0.6.1
+ uglify-js: ^3.1.4
+ wordwrap: ^1.0.0
+ dependenciesMeta:
+ uglify-js:
+ optional: true
+ bin:
+ handlebars: bin/handlebars
+ checksum: 00e68bb5c183fd7b8b63322e6234b5ac8fbb960d712cb3f25587d559c2951d9642df83c04a1172c918c41bcfc81bfbd7a7718bbce93b893e0135fc99edea93ff
+ languageName: node
+ linkType: hard
+
"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2":
version: 1.0.2
resolution: "has-bigints@npm:1.0.2"
@@ -7805,7 +7823,7 @@ __metadata:
languageName: node
linkType: hard
-"minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.7":
+"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7":
version: 1.2.8
resolution: "minimist@npm:1.2.8"
checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0
@@ -8027,6 +8045,13 @@ __metadata:
languageName: node
linkType: hard
+"neo-async@npm:^2.6.2":
+ version: 2.6.2
+ resolution: "neo-async@npm:2.6.2"
+ checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9
+ languageName: node
+ linkType: hard
+
"nitropack@npm:^2.5.2":
version: 2.6.0
resolution: "nitropack@npm:2.6.0"
@@ -8432,6 +8457,7 @@ __metadata:
eslint-plugin-import: ^2.28.1
eslint-plugin-prettier: ^5.0.0
eslint-plugin-unused-imports: ^3.0.0
+ handlebars: ^4.7.8
nuxt: ^3.6.5
perfect-debounce: ^1.0.0
pinia: ^2.1.6
@@ -10167,7 +10193,7 @@ __metadata:
languageName: node
linkType: hard
-"source-map@npm:^0.6.0, source-map@npm:~0.6.1":
+"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1":
version: 0.6.1
resolution: "source-map@npm:0.6.1"
checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2
@@ -10867,6 +10893,15 @@ __metadata:
languageName: node
linkType: hard
+"uglify-js@npm:^3.1.4":
+ version: 3.18.0
+ resolution: "uglify-js@npm:3.18.0"
+ bin:
+ uglifyjs: bin/uglifyjs
+ checksum: 887733d05d4139a94dffd04a5f07ee7d8be70201c016ea48cb82703778b5c48fadbe6e5e7ac956425522f72e657d3eade23f06ae8a0e2eeed2d684bf6cc25e36
+ languageName: node
+ linkType: hard
+
"ultrahtml@npm:^1.2.0":
version: 1.3.0
resolution: "ultrahtml@npm:1.3.0"
@@ -11802,6 +11837,13 @@ __metadata:
languageName: node
linkType: hard
+"wordwrap@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "wordwrap@npm:1.0.0"
+ checksum: 2a44b2788165d0a3de71fd517d4880a8e20ea3a82c080ce46e294f0b68b69a2e49cff5f99c600e275c698a90d12c5ea32aff06c311f0db2eb3f1201f3e7b2a04
+ languageName: node
+ linkType: hard
+
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0":
version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0"