@css-hooks/core 1.0.2 → 1.2.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 +1 -1
- package/cjs/index.js +121 -28
- package/esm/index.js +119 -27
- package/package.json +1 -1
- package/types/index.d.ts +6 -2
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ Please visit [css-hooks.com](https://css-hooks.com) to get started.
|
|
|
50
50
|
- [@css-hooks/react](packages/react): React framework integration
|
|
51
51
|
- [@css-hooks/solid](packages/solid): Solid framework integration
|
|
52
52
|
- [@css-hooks/preact](packages/preact): Preact framework integration
|
|
53
|
-
- [@css-hooks/core](packages/core): Core package (internal use
|
|
53
|
+
- [@css-hooks/core](packages/core): Core package (internal / advanced use cases)
|
|
54
54
|
|
|
55
55
|
## Contributing
|
|
56
56
|
|
package/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.recommended = exports.buildHooksSystem = void 0;
|
|
3
|
+
exports.recommended = exports.buildHooksSystem = exports.genericStringify = void 0;
|
|
4
4
|
function isHookSpec(x) {
|
|
5
5
|
if (!x) {
|
|
6
6
|
return false;
|
|
@@ -15,10 +15,24 @@ function isHookSpec(x) {
|
|
|
15
15
|
if ("or" in x && x.or instanceof Array) {
|
|
16
16
|
return !x.or.some(xx => !isHookSpec(xx));
|
|
17
17
|
}
|
|
18
|
+
if ("and" in x && x.and instanceof Array) {
|
|
19
|
+
return !x.and.some(xx => !isHookSpec(xx));
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
22
|
return false;
|
|
20
23
|
}
|
|
21
|
-
|
|
24
|
+
/** @internal */
|
|
25
|
+
function genericStringify(_, value) {
|
|
26
|
+
if (typeof value === "string") {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
if (typeof value === "number") {
|
|
30
|
+
return `${value}`;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
exports.genericStringify = genericStringify;
|
|
35
|
+
function buildHooksSystem(stringify = genericStringify) {
|
|
22
36
|
return function createHooks(config) {
|
|
23
37
|
const stringifyImpl = (propertyName, value) => {
|
|
24
38
|
return typeof value === "string" && value.startsWith("var(")
|
|
@@ -63,39 +77,118 @@ function buildHooksSystem(stringify) {
|
|
|
63
77
|
});
|
|
64
78
|
return properties;
|
|
65
79
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (!isHookSpec(spec)) {
|
|
79
|
-
return [];
|
|
80
|
+
const css = Object.entries(config)
|
|
81
|
+
.map(([name, definition]) => {
|
|
82
|
+
function nest(input) {
|
|
83
|
+
if (typeof input === "object") {
|
|
84
|
+
if ("and" in input) {
|
|
85
|
+
if (input.and.length > 2) {
|
|
86
|
+
const [left, ...rest] = input.and;
|
|
87
|
+
return { and: [left, nest({ and: rest })] };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
and: input.and.map(item => typeof item === "string" ? item : nest(item)),
|
|
91
|
+
};
|
|
80
92
|
}
|
|
81
|
-
if (
|
|
82
|
-
if (
|
|
83
|
-
|
|
93
|
+
if ("or" in input) {
|
|
94
|
+
if (input.or.length > 2) {
|
|
95
|
+
const [left, ...rest] = input.or;
|
|
96
|
+
return { or: [left, nest({ or: rest })] };
|
|
84
97
|
}
|
|
98
|
+
return {
|
|
99
|
+
or: input.or.map(item => typeof item === "string" ? item : nest(item)),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return input;
|
|
104
|
+
}
|
|
105
|
+
if (!isHookSpec(definition) || typeof definition !== "object") {
|
|
106
|
+
return [name, definition];
|
|
107
|
+
}
|
|
108
|
+
return [name, nest(definition)];
|
|
109
|
+
})
|
|
110
|
+
.flatMap(function css([name, definition]) {
|
|
111
|
+
if (!isHookSpec(definition)) {
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
if (typeof definition === "object") {
|
|
115
|
+
let a, operator, b, extraCSS = [];
|
|
116
|
+
if ("or" in definition) {
|
|
117
|
+
operator = "or";
|
|
118
|
+
[a, b] = definition.or;
|
|
119
|
+
if (!a) {
|
|
85
120
|
return [];
|
|
86
121
|
}
|
|
87
|
-
if (
|
|
88
|
-
return
|
|
122
|
+
if (!b) {
|
|
123
|
+
return css.bind(this)([name, a]);
|
|
89
124
|
}
|
|
90
|
-
|
|
91
|
-
|
|
125
|
+
extraCSS = [
|
|
126
|
+
{
|
|
127
|
+
init: (function aorb(x) {
|
|
128
|
+
const a = `${x}A`;
|
|
129
|
+
const b = `${x}B`;
|
|
130
|
+
return [
|
|
131
|
+
`--${x}-0:var(--${a}-0,var(--${b}-0));`,
|
|
132
|
+
`--${x}-1:var(--${a}-0,var(--${b}-1)) var(--${b}-0,var(--${a}-1)) var(--${a}-1,var(--${b}-1));`,
|
|
133
|
+
].join("");
|
|
134
|
+
})(name),
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
else if ("and" in definition) {
|
|
139
|
+
operator = "and";
|
|
140
|
+
[a, b] = definition.and;
|
|
141
|
+
if (!a) {
|
|
142
|
+
return [];
|
|
92
143
|
}
|
|
93
|
-
if (
|
|
94
|
-
return [
|
|
144
|
+
if (!b) {
|
|
145
|
+
return css.bind(this)([name, a]);
|
|
95
146
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
147
|
+
extraCSS = [
|
|
148
|
+
{
|
|
149
|
+
init: (function aandb(x) {
|
|
150
|
+
const a = `${x}A`;
|
|
151
|
+
const b = `${x}B`;
|
|
152
|
+
return [
|
|
153
|
+
`--${x}-0:var(--${a}-0,var(--${b}-0)) var(--${a}-1,var(--${b}-0)) var(--${b}-1,var(--${a}-0));`,
|
|
154
|
+
`--${x}-1:var(--${a}-1,var(${b}-1));`,
|
|
155
|
+
].join("");
|
|
156
|
+
})(name),
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
if (operator) {
|
|
161
|
+
return [
|
|
162
|
+
...css.bind(this)([`${name}A`, a]),
|
|
163
|
+
...css.bind(this)([`${name}B`, b]),
|
|
164
|
+
...extraCSS,
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const init = `--${name}-0:initial;--${name}-1: ;`;
|
|
169
|
+
let rule;
|
|
170
|
+
if (typeof definition === "string") {
|
|
171
|
+
if (definition.includes("&")) {
|
|
172
|
+
rule = `${definition.replace(/&/g, "*")}{--${name}-0: ;--${name}-1:initial;}`;
|
|
173
|
+
}
|
|
174
|
+
else if (definition.startsWith(":")) {
|
|
175
|
+
rule = `${definition}{--${name}-0: ;--${name}-1:initial;}`;
|
|
176
|
+
}
|
|
177
|
+
else if (definition.startsWith("@")) {
|
|
178
|
+
rule = `${definition}{*{--${name}-0: ;--${name}-1:initial;}}`;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return rule === undefined ? [] : [{ init, rule }];
|
|
182
|
+
})
|
|
183
|
+
.reduce((acc, { init = "", rule = "" }) => ({
|
|
184
|
+
init: acc.init + init,
|
|
185
|
+
rule: acc.rule + rule,
|
|
186
|
+
}), {
|
|
187
|
+
init: "",
|
|
188
|
+
rule: "",
|
|
189
|
+
});
|
|
190
|
+
return [
|
|
191
|
+
`*{${css.init}}${css.rule}`,
|
|
99
192
|
function hooks(properties) {
|
|
100
193
|
return hooksImpl(JSON.parse(JSON.stringify(properties)));
|
|
101
194
|
},
|
package/esm/index.js
CHANGED
|
@@ -12,10 +12,23 @@ function isHookSpec(x) {
|
|
|
12
12
|
if ("or" in x && x.or instanceof Array) {
|
|
13
13
|
return !x.or.some(xx => !isHookSpec(xx));
|
|
14
14
|
}
|
|
15
|
+
if ("and" in x && x.and instanceof Array) {
|
|
16
|
+
return !x.and.some(xx => !isHookSpec(xx));
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
return false;
|
|
17
20
|
}
|
|
18
|
-
|
|
21
|
+
/** @internal */
|
|
22
|
+
export function genericStringify(_, value) {
|
|
23
|
+
if (typeof value === "string") {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "number") {
|
|
27
|
+
return `${value}`;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export function buildHooksSystem(stringify = genericStringify) {
|
|
19
32
|
return function createHooks(config) {
|
|
20
33
|
const stringifyImpl = (propertyName, value) => {
|
|
21
34
|
return typeof value === "string" && value.startsWith("var(")
|
|
@@ -60,39 +73,118 @@ export function buildHooksSystem(stringify) {
|
|
|
60
73
|
});
|
|
61
74
|
return properties;
|
|
62
75
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (!isHookSpec(spec)) {
|
|
76
|
-
return [];
|
|
76
|
+
const css = Object.entries(config)
|
|
77
|
+
.map(([name, definition]) => {
|
|
78
|
+
function nest(input) {
|
|
79
|
+
if (typeof input === "object") {
|
|
80
|
+
if ("and" in input) {
|
|
81
|
+
if (input.and.length > 2) {
|
|
82
|
+
const [left, ...rest] = input.and;
|
|
83
|
+
return { and: [left, nest({ and: rest })] };
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
and: input.and.map(item => typeof item === "string" ? item : nest(item)),
|
|
87
|
+
};
|
|
77
88
|
}
|
|
78
|
-
if (
|
|
79
|
-
if (
|
|
80
|
-
|
|
89
|
+
if ("or" in input) {
|
|
90
|
+
if (input.or.length > 2) {
|
|
91
|
+
const [left, ...rest] = input.or;
|
|
92
|
+
return { or: [left, nest({ or: rest })] };
|
|
81
93
|
}
|
|
94
|
+
return {
|
|
95
|
+
or: input.or.map(item => typeof item === "string" ? item : nest(item)),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return input;
|
|
100
|
+
}
|
|
101
|
+
if (!isHookSpec(definition) || typeof definition !== "object") {
|
|
102
|
+
return [name, definition];
|
|
103
|
+
}
|
|
104
|
+
return [name, nest(definition)];
|
|
105
|
+
})
|
|
106
|
+
.flatMap(function css([name, definition]) {
|
|
107
|
+
if (!isHookSpec(definition)) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
if (typeof definition === "object") {
|
|
111
|
+
let a, operator, b, extraCSS = [];
|
|
112
|
+
if ("or" in definition) {
|
|
113
|
+
operator = "or";
|
|
114
|
+
[a, b] = definition.or;
|
|
115
|
+
if (!a) {
|
|
82
116
|
return [];
|
|
83
117
|
}
|
|
84
|
-
if (
|
|
85
|
-
return
|
|
118
|
+
if (!b) {
|
|
119
|
+
return css.bind(this)([name, a]);
|
|
86
120
|
}
|
|
87
|
-
|
|
88
|
-
|
|
121
|
+
extraCSS = [
|
|
122
|
+
{
|
|
123
|
+
init: (function aorb(x) {
|
|
124
|
+
const a = `${x}A`;
|
|
125
|
+
const b = `${x}B`;
|
|
126
|
+
return [
|
|
127
|
+
`--${x}-0:var(--${a}-0,var(--${b}-0));`,
|
|
128
|
+
`--${x}-1:var(--${a}-0,var(--${b}-1)) var(--${b}-0,var(--${a}-1)) var(--${a}-1,var(--${b}-1));`,
|
|
129
|
+
].join("");
|
|
130
|
+
})(name),
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
else if ("and" in definition) {
|
|
135
|
+
operator = "and";
|
|
136
|
+
[a, b] = definition.and;
|
|
137
|
+
if (!a) {
|
|
138
|
+
return [];
|
|
89
139
|
}
|
|
90
|
-
if (
|
|
91
|
-
return [
|
|
140
|
+
if (!b) {
|
|
141
|
+
return css.bind(this)([name, a]);
|
|
92
142
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
143
|
+
extraCSS = [
|
|
144
|
+
{
|
|
145
|
+
init: (function aandb(x) {
|
|
146
|
+
const a = `${x}A`;
|
|
147
|
+
const b = `${x}B`;
|
|
148
|
+
return [
|
|
149
|
+
`--${x}-0:var(--${a}-0,var(--${b}-0)) var(--${a}-1,var(--${b}-0)) var(--${b}-1,var(--${a}-0));`,
|
|
150
|
+
`--${x}-1:var(--${a}-1,var(${b}-1));`,
|
|
151
|
+
].join("");
|
|
152
|
+
})(name),
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
if (operator) {
|
|
157
|
+
return [
|
|
158
|
+
...css.bind(this)([`${name}A`, a]),
|
|
159
|
+
...css.bind(this)([`${name}B`, b]),
|
|
160
|
+
...extraCSS,
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const init = `--${name}-0:initial;--${name}-1: ;`;
|
|
165
|
+
let rule;
|
|
166
|
+
if (typeof definition === "string") {
|
|
167
|
+
if (definition.includes("&")) {
|
|
168
|
+
rule = `${definition.replace(/&/g, "*")}{--${name}-0: ;--${name}-1:initial;}`;
|
|
169
|
+
}
|
|
170
|
+
else if (definition.startsWith(":")) {
|
|
171
|
+
rule = `${definition}{--${name}-0: ;--${name}-1:initial;}`;
|
|
172
|
+
}
|
|
173
|
+
else if (definition.startsWith("@")) {
|
|
174
|
+
rule = `${definition}{*{--${name}-0: ;--${name}-1:initial;}}`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return rule === undefined ? [] : [{ init, rule }];
|
|
178
|
+
})
|
|
179
|
+
.reduce((acc, { init = "", rule = "" }) => ({
|
|
180
|
+
init: acc.init + init,
|
|
181
|
+
rule: acc.rule + rule,
|
|
182
|
+
}), {
|
|
183
|
+
init: "",
|
|
184
|
+
rule: "",
|
|
185
|
+
});
|
|
186
|
+
return [
|
|
187
|
+
`*{${css.init}}${css.rule}`,
|
|
96
188
|
function hooks(properties) {
|
|
97
189
|
return hooksImpl(JSON.parse(JSON.stringify(properties)));
|
|
98
190
|
},
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
type UnionToIntersection<T> = (T extends any ? (t: T) => any : never) extends (t: infer U) => any ? U : never;
|
|
2
2
|
type HookSpec = `@${"media" | "container"} ${string}` | `:${string}` | `${string}&${string}` | {
|
|
3
|
-
or: Readonly<
|
|
3
|
+
or: Readonly<HookSpec[]>;
|
|
4
|
+
} | {
|
|
5
|
+
and: Readonly<HookSpec[]>;
|
|
4
6
|
};
|
|
5
7
|
export type WithHooks<HookProperties, Properties> = WithHooksImpl<Properties, HookProperties>;
|
|
6
8
|
type WithHooksImpl<Properties, HookProperties, HookPropertiesSub extends HookProperties = HookProperties> = Properties & Partial<UnionToIntersection<HookPropertiesSub extends string ? {
|
|
7
9
|
[K in HookPropertiesSub]: WithHooksImpl<Properties, Exclude<HookProperties, HookPropertiesSub>>;
|
|
8
10
|
} : never>>;
|
|
9
|
-
|
|
11
|
+
/** @internal */
|
|
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>) => readonly [`*{${string}}undefined` | `*{${string}}${string}`, (properties: WithHooks<HookProperties, Properties>) => Properties];
|
|
10
14
|
/**
|
|
11
15
|
* A list of hooks offered as a "sensible default" to solve the most common use cases.
|
|
12
16
|
*/
|