diff --git a/README.md b/README.md
index b85746d..bdc4ddf 100644
--- a/README.md
+++ b/README.md
@@ -441,3 +441,62 @@ Methods:
* [translate(x: string | number, y?: string | number)](./docs/transform.md#translate-x-string-number-y-string-number-)
* [skew(x: string | number, y?: string | number)](./docs/transform.md#skew-x-string-number-y-string-number-)
* [transform(value: string)](./docs/transform.md#transform-value-string-)
+
+## [CSS]()
+
+Method for injecting arbitrary Stitches CSS into the current chain.
+Use this when you need a style that isn’t (yet) covered by the first-class chain methods,
+or when you want to author nested selectors and media queries inline.
+
+```typescript
+
+import { Frame } from "tile-css";
+
+const Hello = Frame()
+ .size(300)
+ .fg("white")
+ .mono(21, { color: "#000" })
+ .css({
+ border: "1px solid #000",
+ boxShadow: "0 10px 24px rgba(0,0,0,.18)",
+ textAlign: "center",
+ })
+ .css({
+ "@media (max-width: 480px)": {
+ width: 240,
+ height: 240,
+ fontSize: 14,
+ },
+ })
+ .element();
+
+function App() {
+ return Hello world :);
+}
+
+export { App }
+```
+
+## [Additional]()
+
+if you chain a method that isn’t provided by a built-in module, it’s treated as a **CSS property** (camelCased) or a
+**Stitches util** key and merged into the style tree. This lets you use one-off properties without writing a new module.
+
+```typescript
+
+import { View } from "tile-css";
+
+const Avatar = View("img")
+ .size(200)
+ .border("1px solid #000")
+ .round(12)
+ .objectFit('fill') // This doesn't exist in the first-class chain methods
+ .objectPosition('20% 20%') // This doesn't exist in the first-class chain methods
+ .element();
+
+function App() {
+ return
+}
+
+export { App }
+```
diff --git a/lib/chain.ts b/lib/chain.ts
index 6cd0613..14f4926 100644
--- a/lib/chain.ts
+++ b/lib/chain.ts
@@ -68,6 +68,8 @@ export function createChain(
const variants: VariantCSS = { ...startingValues?.variants };
const children: Record = { ...startingValues?.children };
+ let self: Chain;
+
const chain: Chain = {
extend: (newElementTag?: Tag) => {
return createChain(stitches, newElementTag || elementTag, {
@@ -80,7 +82,7 @@ export function createChain(
// @ts-ignore
select: (selector: string, subchain: CSS | Chain) => {
children[selector] = subchain;
- return chain;
+ return self;
},
// In your element method:
element: (rawCSS?: CSS) => {
@@ -112,23 +114,49 @@ export function createChain(
},
];
}
-
- return chain;
+ return self;
},
+
css: (rawCSS: CSS) => {
update(rawCSS);
- return chain;
+ return self;
},
};
modules.forEach((m) => m.register(addMethod));
- return chain;
+ const proxy = new Proxy(chain as Chain, {
+ get(target, propKey, receiver) {
+ // Default implemented methods
+ if (propKey in target) {
+ return Reflect.get(target, propKey, receiver);
+ }
+
+ if (typeof propKey !== "string") {
+ return undefined;
+ }
+
+ return (...args: any[]) => {
+ if (!args.length) {
+ return receiver;
+ }
+
+ // Fallback to style property update with given key-value pairs.
+ update({ [propKey]: args[0] });
+
+ return receiver;
+ };
+ },
+ });
+
+ self = proxy as Chain;
+
+ return proxy as Chain;
function addMethod(name: string, fn: ChainMethod) {
chain[name] = (...args: unknown[]) => {
update(fn.apply(chain, [tree, ...args]));
- return chain;
+ return self;
};
}
@@ -157,7 +185,7 @@ export function createChain(
for (const selector in children) {
output[selector] =
typeof children[selector].compile === "function"
- ? children[selector].compile()
+ ? (children[selector] as Chain).compile()
: children[selector];
}
diff --git a/playground/tile.js b/playground/tile.js
index 0d5cd56..33db3dc 100644
--- a/playground/tile.js
+++ b/playground/tile.js
@@ -30,9 +30,9 @@ var Tile = (() => {
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
- // node_modules/.deno/react@18.3.1/node_modules/react/cjs/react.development.js
+ // node_modules/react/cjs/react.development.js
var require_react_development = __commonJS({
- "node_modules/.deno/react@18.3.1/node_modules/react/cjs/react.development.js"(exports, module) {
+ "node_modules/react/cjs/react.development.js"(exports, module) {
"use strict";
if (true) {
(function() {
@@ -1904,9 +1904,9 @@ var Tile = (() => {
}
});
- // node_modules/.deno/react@18.3.1/node_modules/react/index.js
+ // node_modules/react/index.js
var require_react = __commonJS({
- "node_modules/.deno/react@18.3.1/node_modules/react/index.js"(exports, module) {
+ "node_modules/react/index.js"(exports, module) {
"use strict";
if (false) {
module.exports = null;
@@ -1931,7 +1931,7 @@ var Tile = (() => {
style: () => style
});
- // node_modules/.deno/@stitches+react@1.2.8/node_modules/@stitches/react/dist/index.mjs
+ // node_modules/@stitches/react/dist/index.mjs
var import_react = __toESM(require_react(), 1);
var e = "colors";
var t = "sizes";
@@ -3802,6 +3802,7 @@ var Tile = (() => {
let tree = { ...startingValues?.tree };
const variants = { ...startingValues?.variants };
const children = { ...startingValues?.children };
+ let self;
const chain = {
extend: (newElementTag) => {
return createChain(stitches, newElementTag || elementTag, {
@@ -3814,7 +3815,7 @@ var Tile = (() => {
// @ts-ignore
select: (selector, subchain) => {
children[selector] = subchain;
- return chain;
+ return self;
},
// In your element method:
element: (rawCSS) => {
@@ -3839,19 +3840,37 @@ var Tile = (() => {
}
];
}
- return chain;
+ return self;
},
css: (rawCSS) => {
update(rawCSS);
- return chain;
+ return self;
}
};
modules.forEach((m2) => m2.register(addMethod));
- return chain;
+ const proxy = new Proxy(chain, {
+ get(target, propKey, receiver) {
+ if (propKey in target) {
+ return Reflect.get(target, propKey, receiver);
+ }
+ if (typeof propKey !== "string") {
+ return void 0;
+ }
+ return (...args) => {
+ if (!args.length) {
+ return receiver;
+ }
+ update({ [propKey]: args[0] });
+ return receiver;
+ };
+ }
+ });
+ self = proxy;
+ return proxy;
function addMethod(name, fn) {
chain[name] = (...args) => {
update(fn.apply(chain, [tree, ...args]));
- return chain;
+ return self;
};
}
function update(updates) {