mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] component/tags: add inline css tag
This add an important feature: defining completely standalone owl components, with the template/style and javascript code together. closes #284
This commit is contained in:
@@ -6,6 +6,7 @@ import "./directive";
|
||||
import { Fiber } from "./fiber";
|
||||
import "./props_validation";
|
||||
import { Scheduler, scheduler } from "./scheduler";
|
||||
import { activateSheet } from "./styles";
|
||||
|
||||
/**
|
||||
* Owl Component System
|
||||
@@ -199,6 +200,9 @@ export class Component<T extends Env, Props extends {}> {
|
||||
refs: null,
|
||||
scope: null
|
||||
};
|
||||
if (constr.style) {
|
||||
this.__applyStyles(constr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -580,6 +584,20 @@ export class Component<T extends Env, Props extends {}> {
|
||||
return fiber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the stylesheets defined by the component. Note that we need to make
|
||||
* sure all inherited stylesheets are applied as well. We then delete the
|
||||
* `style` key from the constructor to make sure we do not apply it again.
|
||||
*/
|
||||
private __applyStyles(constr) {
|
||||
while (constr && constr.style) {
|
||||
if (constr.hasOwnProperty("style")) {
|
||||
activateSheet(constr.style, constr.name);
|
||||
delete constr.style;
|
||||
}
|
||||
constr = constr.__proto__;
|
||||
}
|
||||
}
|
||||
__getTemplate(qweb: QWeb): string {
|
||||
let p = (<any>this).constructor;
|
||||
if (!p.hasOwnProperty("_template")) {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Owl Style System
|
||||
*
|
||||
* This files contains the Owl code related to processing (extended) css strings
|
||||
* and creating/adding <style> tags to the document head.
|
||||
*/
|
||||
|
||||
export const STYLESHEETS: { [id: string]: HTMLStyleElement } = {};
|
||||
|
||||
function processSheet(str: string): string {
|
||||
const tokens = str.split(/(\{|\}|;)/).map(s => s.trim());
|
||||
const selectorStack: string[] = [];
|
||||
const parts: string[] = [];
|
||||
let rules: string[] = [];
|
||||
function generateRules() {
|
||||
if (rules.length) {
|
||||
parts.push(selectorStack.join(" ") + " {");
|
||||
parts.push(...rules);
|
||||
parts.push("}");
|
||||
rules = [];
|
||||
}
|
||||
}
|
||||
while (tokens.length) {
|
||||
let token = tokens.shift()!;
|
||||
if (token === "}") {
|
||||
generateRules();
|
||||
selectorStack.pop();
|
||||
} else {
|
||||
if (tokens[0] === "{") {
|
||||
generateRules();
|
||||
selectorStack.push(token);
|
||||
tokens.shift();
|
||||
}
|
||||
if (tokens[0] === ";") {
|
||||
rules.push(" " + token + ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
return parts.join("\n");
|
||||
}
|
||||
export function registerSheet(id: string, css: string) {
|
||||
const sheet = document.createElement("style");
|
||||
sheet.innerHTML = processSheet(css);
|
||||
STYLESHEETS[id] = sheet;
|
||||
}
|
||||
|
||||
export function activateSheet(id, name) {
|
||||
const sheet = STYLESHEETS[id];
|
||||
if (!sheet) {
|
||||
throw new Error(
|
||||
`Invalid css stylesheet for component '${name}'. Did you forget to use the 'css' tag helper?`
|
||||
);
|
||||
}
|
||||
sheet.setAttribute("component", name);
|
||||
document.head.appendChild(sheet);
|
||||
}
|
||||
+17
@@ -1,4 +1,5 @@
|
||||
import { QWeb } from "./qweb/index";
|
||||
import { registerSheet } from "./component/styles";
|
||||
|
||||
/**
|
||||
* Owl Tags
|
||||
@@ -25,3 +26,19 @@ export function xml(strings, ...args) {
|
||||
QWeb.registerTemplate(name, value);
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS tag helper for defining inline stylesheets. With this, one can simply define
|
||||
* an inline stylesheet with just the following code:
|
||||
* ```js
|
||||
* class A extends Component {
|
||||
* static style = css`.component-a { color: red; }`;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function css(strings, ...args) {
|
||||
const name = `__sheet__${QWeb.nextId++}`;
|
||||
const value = String.raw(strings, ...args);
|
||||
registerSheet(name, value);
|
||||
return name;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user