@css-hooks/core 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/cjs/index.js +67 -50
- package/esm/index.js +67 -50
- package/package.json +1 -1
- package/types/index.d.ts +9 -1
package/README.md
CHANGED
|
@@ -23,22 +23,26 @@ styles to a link:
|
|
|
23
23
|
```jsx
|
|
24
24
|
<a
|
|
25
25
|
href="https://css-hooks.com/"
|
|
26
|
-
style={
|
|
26
|
+
style={css({
|
|
27
27
|
color: "#03f",
|
|
28
|
-
|
|
28
|
+
fontSize: "1rem",
|
|
29
|
+
"&:hover": {
|
|
29
30
|
color: "#09f",
|
|
30
31
|
},
|
|
31
|
-
active: {
|
|
32
|
+
"&:active": {
|
|
32
33
|
color: "#e33",
|
|
33
34
|
},
|
|
35
|
+
"@media (1000px <= width)": {
|
|
36
|
+
fontSize: "1.25rem",
|
|
37
|
+
},
|
|
34
38
|
})}
|
|
35
39
|
>
|
|
36
40
|
Hooks
|
|
37
41
|
</a>
|
|
38
42
|
```
|
|
39
43
|
|
|
40
|
-
Notably, the `
|
|
41
|
-
|
|
44
|
+
Notably, the `css` function is pure. It simply returns a flat style object that
|
|
45
|
+
is compatible with the `style` prop, creating dynamic property values that
|
|
42
46
|
change under various conditions through CSS variables.
|
|
43
47
|
|
|
44
48
|
## Documentation
|
package/cjs/index.js
CHANGED
|
@@ -32,52 +32,38 @@ function genericStringify(_, value) {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
exports.genericStringify = genericStringify;
|
|
35
|
+
function hash(obj) {
|
|
36
|
+
const jsonString = JSON.stringify(obj);
|
|
37
|
+
let hashValue = 0;
|
|
38
|
+
for (let i = 0; i < jsonString.length; i++) {
|
|
39
|
+
const charCode = jsonString.charCodeAt(i);
|
|
40
|
+
hashValue = (hashValue << 5) - hashValue + charCode;
|
|
41
|
+
hashValue &= 0x7fffffff;
|
|
42
|
+
}
|
|
43
|
+
return hashValue.toString(36);
|
|
44
|
+
}
|
|
35
45
|
function buildHooksSystem(stringify = genericStringify) {
|
|
36
|
-
return function createHooks(config) {
|
|
46
|
+
return function createHooks(config, options) {
|
|
37
47
|
const stringifyImpl = (propertyName, value) => {
|
|
38
48
|
return typeof value === "string" && value.startsWith("var(")
|
|
39
49
|
? value
|
|
40
50
|
: stringify(propertyName, value);
|
|
41
51
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
value);
|
|
52
|
+
const hookId = (options === null || options === void 0 ? void 0 : options.hookNameToId) ||
|
|
53
|
+
((hookName) => {
|
|
54
|
+
const specHash = hash(config[hookName]);
|
|
55
|
+
return (options === null || options === void 0 ? void 0 : options.debug)
|
|
56
|
+
? `${hookName.replace(/[^A-Za-z0-9-]/g, "_")}-${specHash}`
|
|
57
|
+
: specHash;
|
|
49
58
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (v === null) {
|
|
56
|
-
v = fallback(propertyName);
|
|
57
|
-
}
|
|
58
|
-
if (v === null) {
|
|
59
|
-
v = "unset";
|
|
60
|
-
}
|
|
61
|
-
return v;
|
|
62
|
-
});
|
|
63
|
-
for (const propertyName in hook) {
|
|
64
|
-
const v1 = stringifyImpl(propertyName, hook[propertyName]);
|
|
65
|
-
if (v1 !== null) {
|
|
66
|
-
let v0 = fallback(propertyName);
|
|
67
|
-
if (v0 === null) {
|
|
68
|
-
v0 = "unset";
|
|
69
|
-
}
|
|
70
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
71
|
-
properties[propertyName] =
|
|
72
|
-
`var(--${String(key)}-1, ${v1}) var(--${String(key)}-0, ${v0})`;
|
|
73
|
-
/* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
delete properties[key];
|
|
59
|
+
function forEachHook(properties, callback) {
|
|
60
|
+
return Object.entries(properties)
|
|
61
|
+
.filter(([key]) => key in config)
|
|
62
|
+
.forEach(([hookName, value]) => {
|
|
63
|
+
callback(hookName, value);
|
|
77
64
|
});
|
|
78
|
-
return properties;
|
|
79
65
|
}
|
|
80
|
-
const
|
|
66
|
+
const hooks = Object.entries(config)
|
|
81
67
|
.map(([name, definition]) => {
|
|
82
68
|
function nest(input) {
|
|
83
69
|
if (typeof input === "object") {
|
|
@@ -107,12 +93,12 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
107
93
|
}
|
|
108
94
|
return [name, nest(definition)];
|
|
109
95
|
})
|
|
110
|
-
.flatMap(
|
|
96
|
+
.flatMap(([name, definition]) => (function hooksCSS(name, definition) {
|
|
111
97
|
if (!isHookSpec(definition)) {
|
|
112
98
|
return [];
|
|
113
99
|
}
|
|
114
100
|
if (typeof definition === "object") {
|
|
115
|
-
let a, operator, b,
|
|
101
|
+
let a, operator, b, extraHooksCSS = [];
|
|
116
102
|
if ("or" in definition) {
|
|
117
103
|
operator = "or";
|
|
118
104
|
[a, b] = definition.or;
|
|
@@ -120,9 +106,9 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
120
106
|
return [];
|
|
121
107
|
}
|
|
122
108
|
if (!b) {
|
|
123
|
-
return
|
|
109
|
+
return hooksCSS(name, a);
|
|
124
110
|
}
|
|
125
|
-
|
|
111
|
+
extraHooksCSS = [
|
|
126
112
|
{
|
|
127
113
|
init: (function aorb(x) {
|
|
128
114
|
const a = `${x}A`;
|
|
@@ -142,9 +128,9 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
142
128
|
return [];
|
|
143
129
|
}
|
|
144
130
|
if (!b) {
|
|
145
|
-
return
|
|
131
|
+
return hooksCSS(name, a);
|
|
146
132
|
}
|
|
147
|
-
|
|
133
|
+
extraHooksCSS = [
|
|
148
134
|
{
|
|
149
135
|
init: (function aandb(x) {
|
|
150
136
|
const a = `${x}A`;
|
|
@@ -159,9 +145,9 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
159
145
|
}
|
|
160
146
|
if (operator) {
|
|
161
147
|
return [
|
|
162
|
-
...
|
|
163
|
-
...
|
|
164
|
-
...
|
|
148
|
+
...hooksCSS(`${name}A`, a),
|
|
149
|
+
...hooksCSS(`${name}B`, b),
|
|
150
|
+
...extraHooksCSS,
|
|
165
151
|
];
|
|
166
152
|
}
|
|
167
153
|
}
|
|
@@ -179,7 +165,7 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
179
165
|
}
|
|
180
166
|
}
|
|
181
167
|
return rule === undefined ? [] : [{ init, rule }];
|
|
182
|
-
})
|
|
168
|
+
})(hookId(name), definition))
|
|
183
169
|
.reduce((acc, { init = "", rule = "" }) => ({
|
|
184
170
|
init: acc.init + init,
|
|
185
171
|
rule: acc.rule + rule,
|
|
@@ -187,10 +173,39 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
187
173
|
init: "",
|
|
188
174
|
rule: "",
|
|
189
175
|
});
|
|
176
|
+
function cssImpl(properties, fallback = propertyName => stringifyImpl(propertyName, properties[propertyName])) {
|
|
177
|
+
forEachHook(properties, (hookName, innerProperties) => {
|
|
178
|
+
cssImpl(innerProperties, propertyName => {
|
|
179
|
+
let v = stringifyImpl(propertyName, innerProperties[propertyName]);
|
|
180
|
+
if (v === null) {
|
|
181
|
+
v = fallback(propertyName);
|
|
182
|
+
}
|
|
183
|
+
if (v === null) {
|
|
184
|
+
v = "unset";
|
|
185
|
+
}
|
|
186
|
+
return v;
|
|
187
|
+
});
|
|
188
|
+
for (const propertyName in innerProperties) {
|
|
189
|
+
const v1 = stringifyImpl(propertyName, innerProperties[propertyName]);
|
|
190
|
+
if (v1 !== null) {
|
|
191
|
+
let v0 = fallback(propertyName);
|
|
192
|
+
if (v0 === null) {
|
|
193
|
+
v0 = "unset";
|
|
194
|
+
}
|
|
195
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
196
|
+
properties[propertyName] =
|
|
197
|
+
`var(--${hookId(hookName)}-1, ${v1}) var(--${hookId(hookName)}-0, ${v0})`;
|
|
198
|
+
/* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
delete properties[hookName];
|
|
202
|
+
});
|
|
203
|
+
return properties;
|
|
204
|
+
}
|
|
190
205
|
return [
|
|
191
|
-
`*{${
|
|
192
|
-
function
|
|
193
|
-
return
|
|
206
|
+
`*{${hooks.init}}${hooks.rule}`,
|
|
207
|
+
function css(properties) {
|
|
208
|
+
return cssImpl(JSON.parse(JSON.stringify(properties)));
|
|
194
209
|
},
|
|
195
210
|
];
|
|
196
211
|
};
|
|
@@ -198,6 +213,8 @@ function buildHooksSystem(stringify = genericStringify) {
|
|
|
198
213
|
exports.buildHooksSystem = buildHooksSystem;
|
|
199
214
|
/**
|
|
200
215
|
* A list of hooks offered as a "sensible default" to solve the most common use cases.
|
|
216
|
+
*
|
|
217
|
+
* @deprecated Use the `@css-hooks/recommended` package instead.
|
|
201
218
|
*/
|
|
202
219
|
exports.recommended = {
|
|
203
220
|
active: ":active",
|
package/esm/index.js
CHANGED
|
@@ -28,52 +28,38 @@ export function genericStringify(_, value) {
|
|
|
28
28
|
}
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
|
+
function hash(obj) {
|
|
32
|
+
const jsonString = JSON.stringify(obj);
|
|
33
|
+
let hashValue = 0;
|
|
34
|
+
for (let i = 0; i < jsonString.length; i++) {
|
|
35
|
+
const charCode = jsonString.charCodeAt(i);
|
|
36
|
+
hashValue = (hashValue << 5) - hashValue + charCode;
|
|
37
|
+
hashValue &= 0x7fffffff;
|
|
38
|
+
}
|
|
39
|
+
return hashValue.toString(36);
|
|
40
|
+
}
|
|
31
41
|
export function buildHooksSystem(stringify = genericStringify) {
|
|
32
|
-
return function createHooks(config) {
|
|
42
|
+
return function createHooks(config, options) {
|
|
33
43
|
const stringifyImpl = (propertyName, value) => {
|
|
34
44
|
return typeof value === "string" && value.startsWith("var(")
|
|
35
45
|
? value
|
|
36
46
|
: stringify(propertyName, value);
|
|
37
47
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
value);
|
|
48
|
+
const hookId = (options === null || options === void 0 ? void 0 : options.hookNameToId) ||
|
|
49
|
+
((hookName) => {
|
|
50
|
+
const specHash = hash(config[hookName]);
|
|
51
|
+
return (options === null || options === void 0 ? void 0 : options.debug)
|
|
52
|
+
? `${hookName.replace(/[^A-Za-z0-9-]/g, "_")}-${specHash}`
|
|
53
|
+
: specHash;
|
|
45
54
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (v === null) {
|
|
52
|
-
v = fallback(propertyName);
|
|
53
|
-
}
|
|
54
|
-
if (v === null) {
|
|
55
|
-
v = "unset";
|
|
56
|
-
}
|
|
57
|
-
return v;
|
|
58
|
-
});
|
|
59
|
-
for (const propertyName in hook) {
|
|
60
|
-
const v1 = stringifyImpl(propertyName, hook[propertyName]);
|
|
61
|
-
if (v1 !== null) {
|
|
62
|
-
let v0 = fallback(propertyName);
|
|
63
|
-
if (v0 === null) {
|
|
64
|
-
v0 = "unset";
|
|
65
|
-
}
|
|
66
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
67
|
-
properties[propertyName] =
|
|
68
|
-
`var(--${String(key)}-1, ${v1}) var(--${String(key)}-0, ${v0})`;
|
|
69
|
-
/* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
delete properties[key];
|
|
55
|
+
function forEachHook(properties, callback) {
|
|
56
|
+
return Object.entries(properties)
|
|
57
|
+
.filter(([key]) => key in config)
|
|
58
|
+
.forEach(([hookName, value]) => {
|
|
59
|
+
callback(hookName, value);
|
|
73
60
|
});
|
|
74
|
-
return properties;
|
|
75
61
|
}
|
|
76
|
-
const
|
|
62
|
+
const hooks = Object.entries(config)
|
|
77
63
|
.map(([name, definition]) => {
|
|
78
64
|
function nest(input) {
|
|
79
65
|
if (typeof input === "object") {
|
|
@@ -103,12 +89,12 @@ export function buildHooksSystem(stringify = genericStringify) {
|
|
|
103
89
|
}
|
|
104
90
|
return [name, nest(definition)];
|
|
105
91
|
})
|
|
106
|
-
.flatMap(
|
|
92
|
+
.flatMap(([name, definition]) => (function hooksCSS(name, definition) {
|
|
107
93
|
if (!isHookSpec(definition)) {
|
|
108
94
|
return [];
|
|
109
95
|
}
|
|
110
96
|
if (typeof definition === "object") {
|
|
111
|
-
let a, operator, b,
|
|
97
|
+
let a, operator, b, extraHooksCSS = [];
|
|
112
98
|
if ("or" in definition) {
|
|
113
99
|
operator = "or";
|
|
114
100
|
[a, b] = definition.or;
|
|
@@ -116,9 +102,9 @@ export function buildHooksSystem(stringify = genericStringify) {
|
|
|
116
102
|
return [];
|
|
117
103
|
}
|
|
118
104
|
if (!b) {
|
|
119
|
-
return
|
|
105
|
+
return hooksCSS(name, a);
|
|
120
106
|
}
|
|
121
|
-
|
|
107
|
+
extraHooksCSS = [
|
|
122
108
|
{
|
|
123
109
|
init: (function aorb(x) {
|
|
124
110
|
const a = `${x}A`;
|
|
@@ -138,9 +124,9 @@ export function buildHooksSystem(stringify = genericStringify) {
|
|
|
138
124
|
return [];
|
|
139
125
|
}
|
|
140
126
|
if (!b) {
|
|
141
|
-
return
|
|
127
|
+
return hooksCSS(name, a);
|
|
142
128
|
}
|
|
143
|
-
|
|
129
|
+
extraHooksCSS = [
|
|
144
130
|
{
|
|
145
131
|
init: (function aandb(x) {
|
|
146
132
|
const a = `${x}A`;
|
|
@@ -155,9 +141,9 @@ export function buildHooksSystem(stringify = genericStringify) {
|
|
|
155
141
|
}
|
|
156
142
|
if (operator) {
|
|
157
143
|
return [
|
|
158
|
-
...
|
|
159
|
-
...
|
|
160
|
-
...
|
|
144
|
+
...hooksCSS(`${name}A`, a),
|
|
145
|
+
...hooksCSS(`${name}B`, b),
|
|
146
|
+
...extraHooksCSS,
|
|
161
147
|
];
|
|
162
148
|
}
|
|
163
149
|
}
|
|
@@ -175,7 +161,7 @@ export function buildHooksSystem(stringify = genericStringify) {
|
|
|
175
161
|
}
|
|
176
162
|
}
|
|
177
163
|
return rule === undefined ? [] : [{ init, rule }];
|
|
178
|
-
})
|
|
164
|
+
})(hookId(name), definition))
|
|
179
165
|
.reduce((acc, { init = "", rule = "" }) => ({
|
|
180
166
|
init: acc.init + init,
|
|
181
167
|
rule: acc.rule + rule,
|
|
@@ -183,16 +169,47 @@ export function buildHooksSystem(stringify = genericStringify) {
|
|
|
183
169
|
init: "",
|
|
184
170
|
rule: "",
|
|
185
171
|
});
|
|
172
|
+
function cssImpl(properties, fallback = propertyName => stringifyImpl(propertyName, properties[propertyName])) {
|
|
173
|
+
forEachHook(properties, (hookName, innerProperties) => {
|
|
174
|
+
cssImpl(innerProperties, propertyName => {
|
|
175
|
+
let v = stringifyImpl(propertyName, innerProperties[propertyName]);
|
|
176
|
+
if (v === null) {
|
|
177
|
+
v = fallback(propertyName);
|
|
178
|
+
}
|
|
179
|
+
if (v === null) {
|
|
180
|
+
v = "unset";
|
|
181
|
+
}
|
|
182
|
+
return v;
|
|
183
|
+
});
|
|
184
|
+
for (const propertyName in innerProperties) {
|
|
185
|
+
const v1 = stringifyImpl(propertyName, innerProperties[propertyName]);
|
|
186
|
+
if (v1 !== null) {
|
|
187
|
+
let v0 = fallback(propertyName);
|
|
188
|
+
if (v0 === null) {
|
|
189
|
+
v0 = "unset";
|
|
190
|
+
}
|
|
191
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
192
|
+
properties[propertyName] =
|
|
193
|
+
`var(--${hookId(hookName)}-1, ${v1}) var(--${hookId(hookName)}-0, ${v0})`;
|
|
194
|
+
/* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any */
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
delete properties[hookName];
|
|
198
|
+
});
|
|
199
|
+
return properties;
|
|
200
|
+
}
|
|
186
201
|
return [
|
|
187
|
-
`*{${
|
|
188
|
-
function
|
|
189
|
-
return
|
|
202
|
+
`*{${hooks.init}}${hooks.rule}`,
|
|
203
|
+
function css(properties) {
|
|
204
|
+
return cssImpl(JSON.parse(JSON.stringify(properties)));
|
|
190
205
|
},
|
|
191
206
|
];
|
|
192
207
|
};
|
|
193
208
|
}
|
|
194
209
|
/**
|
|
195
210
|
* A list of hooks offered as a "sensible default" to solve the most common use cases.
|
|
211
|
+
*
|
|
212
|
+
* @deprecated Use the `@css-hooks/recommended` package instead.
|
|
196
213
|
*/
|
|
197
214
|
export const recommended = {
|
|
198
215
|
active: ":active",
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -10,9 +10,17 @@ type WithHooksImpl<Properties, HookProperties, HookPropertiesSub extends HookPro
|
|
|
10
10
|
} : never>>;
|
|
11
11
|
/** @internal */
|
|
12
12
|
export declare function genericStringify(_: unknown, value: unknown): string | null;
|
|
13
|
-
export declare function buildHooksSystem<Properties = Record<string, unknown>>(stringify?: (propertyName: keyof Properties, value: unknown) => string | null): <HookProperties extends string>(config: Record<HookProperties, HookSpec
|
|
13
|
+
export declare function buildHooksSystem<Properties = Record<string, unknown>>(stringify?: (propertyName: keyof Properties, value: unknown) => string | null): <HookProperties extends string>(config: Record<HookProperties, HookSpec>, options?: {
|
|
14
|
+
debug?: boolean; /** @internal */
|
|
15
|
+
hookNameToId?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
debug?: undefined;
|
|
18
|
+
/** @internal */ hookNameToId?: (hookName: string) => string;
|
|
19
|
+
} | undefined) => readonly [`*{${string}}undefined` | `*{${string}}${string}`, (properties: WithHooks<HookProperties, Properties>) => Properties];
|
|
14
20
|
/**
|
|
15
21
|
* A list of hooks offered as a "sensible default" to solve the most common use cases.
|
|
22
|
+
*
|
|
23
|
+
* @deprecated Use the `@css-hooks/recommended` package instead.
|
|
16
24
|
*/
|
|
17
25
|
export declare const recommended: {
|
|
18
26
|
readonly active: ":active";
|