css-engine-test-pb 0.0.1

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.
@@ -0,0 +1,13 @@
1
+ import { StyleRule, StyleBucket } from './types';
2
+ interface CompiledRule {
3
+ className: string;
4
+ cssText: string;
5
+ bucket: StyleBucket;
6
+ }
7
+ export declare class StyleCompiler {
8
+ compile(styleDefinition: StyleRule): CompiledRule[];
9
+ private processProperties;
10
+ private processPseudos;
11
+ private processMediaQueries;
12
+ }
13
+ export {};
@@ -0,0 +1,56 @@
1
+ import { createClassName } from './utils/hash';
2
+ import { camelToKebab, isPseudoSelector, isMediaQuery, determineBucket } from './utils';
3
+ export class StyleCompiler {
4
+ compile(styleDefinition) {
5
+ const rules = [];
6
+ this.processProperties(styleDefinition, rules);
7
+ this.processPseudos(styleDefinition, rules);
8
+ this.processMediaQueries(styleDefinition, rules);
9
+ return rules;
10
+ }
11
+ processProperties(styles, rules, pseudo, media) {
12
+ Object.entries(styles).forEach(([property, value]) => {
13
+ if (isPseudoSelector(property) || isMediaQuery(property)) {
14
+ return;
15
+ }
16
+ if (value === undefined || value === null) {
17
+ return;
18
+ }
19
+ const kebabProperty = camelToKebab(property);
20
+ const hashInput = `${kebabProperty}:${value}${pseudo || ''}${media || ''}`;
21
+ const className = createClassName(hashInput);
22
+ const selector = pseudo ? `.${className}${pseudo}` : `.${className}`;
23
+ const cssRule = `${selector} { ${kebabProperty}: ${value}; }`;
24
+ const bucket = determineBucket(pseudo, media);
25
+ let cssText = cssRule;
26
+ if (media) {
27
+ cssText = `${media} { ${cssRule} }`;
28
+ }
29
+ rules.push({
30
+ className,
31
+ cssText,
32
+ bucket
33
+ });
34
+ });
35
+ }
36
+ processPseudos(styleDefinition, rules) {
37
+ Object.entries(styleDefinition).forEach(([key, value]) => {
38
+ if (isPseudoSelector(key) && value) {
39
+ this.processProperties(value, rules, key);
40
+ }
41
+ });
42
+ }
43
+ processMediaQueries(styleDefinition, rules) {
44
+ Object.entries(styleDefinition).forEach(([key, value]) => {
45
+ if (isMediaQuery(key) && value) {
46
+ const nestedStyles = value;
47
+ this.processProperties(nestedStyles, rules, undefined, key);
48
+ Object.entries(nestedStyles).forEach(([nestedKey, nestedValue]) => {
49
+ if (isPseudoSelector(nestedKey) && nestedValue) {
50
+ this.processProperties(nestedValue, rules, nestedKey, key);
51
+ }
52
+ });
53
+ }
54
+ });
55
+ }
56
+ }
@@ -0,0 +1,13 @@
1
+ import { StyleRule, StyleSlots, GeneratedClasses } from './types';
2
+ export declare class StyleEngine {
3
+ private compiler;
4
+ private insertion;
5
+ private cache;
6
+ constructor();
7
+ createStyle(styleDefinition: StyleRule): string;
8
+ createStyles(slots: StyleSlots): GeneratedClasses;
9
+ getCSSString(): string;
10
+ clear(): void;
11
+ }
12
+ export declare function getGlobalEngine(): StyleEngine;
13
+ export declare function resetGlobalEngine(): void;
package/dist/engine.js ADDED
@@ -0,0 +1,52 @@
1
+ import { StyleCompiler } from './compiler';
2
+ import { InsertionFactory } from './insertionFactory';
3
+ export class StyleEngine {
4
+ constructor() {
5
+ this.compiler = new StyleCompiler();
6
+ this.insertion = new InsertionFactory();
7
+ this.cache = new Map();
8
+ }
9
+ createStyle(styleDefinition) {
10
+ const cacheKey = JSON.stringify(styleDefinition);
11
+ if (this.cache.has(cacheKey)) {
12
+ return this.cache.get(cacheKey);
13
+ }
14
+ const rules = this.compiler.compile(styleDefinition);
15
+ rules.forEach(rule => {
16
+ this.insertion.insertRule(rule.cssText, rule.bucket);
17
+ });
18
+ const classNames = Array.from(new Set(rules.map(r => r.className))).join(' ');
19
+ this.cache.set(cacheKey, classNames);
20
+ return classNames;
21
+ }
22
+ createStyles(slots) {
23
+ const classes = {};
24
+ Object.entries(slots).forEach(([slotName, styleDefinition]) => {
25
+ const resolvedStyle = typeof styleDefinition === 'function'
26
+ ? styleDefinition()
27
+ : styleDefinition;
28
+ classes[slotName] = this.createStyle(resolvedStyle);
29
+ });
30
+ return classes;
31
+ }
32
+ getCSSString() {
33
+ return this.insertion.getCSSString();
34
+ }
35
+ clear() {
36
+ this.insertion.clear();
37
+ this.cache.clear();
38
+ }
39
+ }
40
+ let globalEngine = null;
41
+ export function getGlobalEngine() {
42
+ if (!globalEngine) {
43
+ globalEngine = new StyleEngine();
44
+ }
45
+ return globalEngine;
46
+ }
47
+ export function resetGlobalEngine() {
48
+ if (globalEngine) {
49
+ globalEngine.clear();
50
+ }
51
+ globalEngine = null;
52
+ }
@@ -0,0 +1,4 @@
1
+ export { makeStyles } from './makeStyles';
2
+ export { makeResetStyles } from './makeResetStyles';
3
+ export { mergeClasses } from './mergeClasses';
4
+ export { CSSValue, CSSProperties, CSSPseudos, CSSMediaQueries, StyleRule, StyleDefinition, StyleBucket, CSSRule, GeneratedClasses, StyleSheet, StyleEngineConfig, MakeStylesFunction, StyleSlots } from './types';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { makeStyles } from './makeStyles';
2
+ export { makeResetStyles } from './makeResetStyles';
3
+ export { mergeClasses } from './mergeClasses';
4
+ export { StyleBucket } from './types';
@@ -0,0 +1,10 @@
1
+ import { StyleBucket } from './types';
2
+ export declare class InsertionFactory {
3
+ private bucketElements;
4
+ private bucketRules;
5
+ private bucketOrder;
6
+ constructor();
7
+ insertRule(cssRule: string, bucket: StyleBucket): void;
8
+ getCSSString(): string;
9
+ clear(): void;
10
+ }
@@ -0,0 +1,57 @@
1
+ import { StyleBucket } from './types';
2
+ export class InsertionFactory {
3
+ constructor() {
4
+ this.bucketElements = new Map();
5
+ this.bucketRules = new Map();
6
+ this.bucketOrder = [
7
+ StyleBucket.RESET,
8
+ StyleBucket.DEFAULT,
9
+ StyleBucket.LINK,
10
+ StyleBucket.VISITED,
11
+ StyleBucket.FOCUS_VISIBLE,
12
+ StyleBucket.FOCUS_WITHIN,
13
+ StyleBucket.FOCUS,
14
+ StyleBucket.HOVER,
15
+ StyleBucket.ACTIVE,
16
+ StyleBucket.AT_RULE,
17
+ StyleBucket.KEYFRAME,
18
+ StyleBucket.FALLBACK,
19
+ ];
20
+ this.bucketOrder.forEach(bucket => {
21
+ const styleElement = document.createElement('style');
22
+ styleElement.setAttribute('data-bucket', bucket);
23
+ document.head.appendChild(styleElement);
24
+ this.bucketElements.set(bucket, styleElement);
25
+ this.bucketRules.set(bucket, new Set());
26
+ });
27
+ }
28
+ insertRule(cssRule, bucket) {
29
+ const bucketSet = this.bucketRules.get(bucket);
30
+ const styleElement = this.bucketElements.get(bucket);
31
+ if (!bucketSet || !styleElement) {
32
+ console.warn(`Unknown bucket: ${bucket}`);
33
+ return;
34
+ }
35
+ if (bucketSet.has(cssRule)) {
36
+ return;
37
+ }
38
+ bucketSet.add(cssRule);
39
+ styleElement.textContent += cssRule + '\n';
40
+ }
41
+ getCSSString() {
42
+ const allRules = [];
43
+ this.bucketOrder.forEach(bucket => {
44
+ const styleElement = this.bucketElements.get(bucket);
45
+ if (styleElement && styleElement.textContent) {
46
+ allRules.push(styleElement.textContent);
47
+ }
48
+ });
49
+ return allRules.join('');
50
+ }
51
+ clear() {
52
+ this.bucketRules.forEach(set => set.clear());
53
+ this.bucketElements.forEach(el => {
54
+ el.textContent = '';
55
+ });
56
+ }
57
+ }
@@ -0,0 +1,2 @@
1
+ import { StyleRule } from './types';
2
+ export declare function makeResetStyles(styleDefinition: StyleRule): string;
@@ -0,0 +1,5 @@
1
+ import { getGlobalEngine } from './engine';
2
+ export function makeResetStyles(styleDefinition) {
3
+ const engine = getGlobalEngine();
4
+ return engine.createStyle(styleDefinition);
5
+ }
@@ -0,0 +1,2 @@
1
+ import { StyleSlots } from './types';
2
+ export declare function makeStyles(slots: StyleSlots): () => import("./types").GeneratedClasses;
@@ -0,0 +1,6 @@
1
+ import { getGlobalEngine } from './engine';
2
+ export function makeStyles(slots) {
3
+ const engine = getGlobalEngine();
4
+ const classes = engine.createStyles(slots);
5
+ return () => classes;
6
+ }
@@ -0,0 +1 @@
1
+ export declare function mergeClasses(...classNames: (string | false | null | undefined)[]): string;
@@ -0,0 +1,3 @@
1
+ export function mergeClasses(...classNames) {
2
+ return classNames.filter(Boolean).join(' ');
3
+ }
@@ -0,0 +1,143 @@
1
+ export type CSSValue = string | number;
2
+ export interface CSSProperties {
3
+ display?: CSSValue;
4
+ position?: CSSValue;
5
+ top?: CSSValue;
6
+ right?: CSSValue;
7
+ bottom?: CSSValue;
8
+ left?: CSSValue;
9
+ width?: CSSValue;
10
+ height?: CSSValue;
11
+ minWidth?: CSSValue;
12
+ minHeight?: CSSValue;
13
+ maxWidth?: CSSValue;
14
+ maxHeight?: CSSValue;
15
+ flex?: CSSValue;
16
+ flexDirection?: CSSValue;
17
+ flexWrap?: CSSValue;
18
+ flexGrow?: CSSValue;
19
+ flexShrink?: CSSValue;
20
+ flexBasis?: CSSValue;
21
+ justifyContent?: CSSValue;
22
+ alignItems?: CSSValue;
23
+ alignContent?: CSSValue;
24
+ alignSelf?: CSSValue;
25
+ order?: CSSValue;
26
+ gap?: CSSValue;
27
+ gridTemplateColumns?: CSSValue;
28
+ gridTemplateRows?: CSSValue;
29
+ gridColumn?: CSSValue;
30
+ gridRow?: CSSValue;
31
+ margin?: CSSValue;
32
+ marginTop?: CSSValue;
33
+ marginRight?: CSSValue;
34
+ marginBottom?: CSSValue;
35
+ marginLeft?: CSSValue;
36
+ padding?: CSSValue;
37
+ paddingTop?: CSSValue;
38
+ paddingRight?: CSSValue;
39
+ paddingBottom?: CSSValue;
40
+ paddingLeft?: CSSValue;
41
+ color?: CSSValue;
42
+ fontSize?: CSSValue;
43
+ fontWeight?: CSSValue;
44
+ fontFamily?: CSSValue;
45
+ lineHeight?: CSSValue;
46
+ textAlign?: CSSValue;
47
+ textDecoration?: CSSValue;
48
+ textTransform?: CSSValue;
49
+ letterSpacing?: CSSValue;
50
+ background?: CSSValue;
51
+ backgroundColor?: CSSValue;
52
+ backgroundImage?: CSSValue;
53
+ backgroundSize?: CSSValue;
54
+ backgroundPosition?: CSSValue;
55
+ backgroundRepeat?: CSSValue;
56
+ border?: CSSValue;
57
+ borderTop?: CSSValue;
58
+ borderRight?: CSSValue;
59
+ borderBottom?: CSSValue;
60
+ borderLeft?: CSSValue;
61
+ borderWidth?: CSSValue;
62
+ borderStyle?: CSSValue;
63
+ borderColor?: CSSValue;
64
+ borderRadius?: CSSValue;
65
+ opacity?: CSSValue;
66
+ boxShadow?: CSSValue;
67
+ transform?: CSSValue;
68
+ transition?: CSSValue;
69
+ animation?: CSSValue;
70
+ overflow?: CSSValue;
71
+ overflowX?: CSSValue;
72
+ overflowY?: CSSValue;
73
+ cursor?: CSSValue;
74
+ pointerEvents?: CSSValue;
75
+ zIndex?: CSSValue;
76
+ visibility?: CSSValue;
77
+ content?: CSSValue;
78
+ [key: string]: CSSValue | undefined;
79
+ }
80
+ export interface CSSPseudos {
81
+ ':hover'?: CSSProperties;
82
+ ':focus'?: CSSProperties;
83
+ ':active'?: CSSProperties;
84
+ ':disabled'?: CSSProperties;
85
+ ':visited'?: CSSProperties;
86
+ ':focus-visible'?: CSSProperties;
87
+ ':focus-within'?: CSSProperties;
88
+ '::before'?: CSSProperties;
89
+ '::after'?: CSSProperties;
90
+ '::placeholder'?: CSSProperties;
91
+ [key: string]: CSSProperties | undefined;
92
+ }
93
+ export interface CSSMediaQueries {
94
+ '@media (min-width: 480px)'?: CSSProperties & CSSPseudos;
95
+ '@media (min-width: 768px)'?: CSSProperties & CSSPseudos;
96
+ '@media (min-width: 1024px)'?: CSSProperties & CSSPseudos;
97
+ '@media (min-width: 1440px)'?: CSSProperties & CSSPseudos;
98
+ '@media (prefers-color-scheme: dark)'?: CSSProperties & CSSPseudos;
99
+ '@media (prefers-reduced-motion: reduce)'?: CSSProperties & CSSPseudos;
100
+ [key: string]: (CSSProperties & CSSPseudos) | undefined;
101
+ }
102
+ export type StyleRule = CSSProperties & CSSPseudos & CSSMediaQueries;
103
+ export type StyleDefinition = StyleRule | (() => StyleRule);
104
+ export declare enum StyleBucket {
105
+ RESET = "d",
106
+ DEFAULT = "l",
107
+ LINK = "v",
108
+ VISITED = "w",
109
+ FOCUS_VISIBLE = "f",
110
+ FOCUS_WITHIN = "i",
111
+ FOCUS = "o",
112
+ HOVER = "h",
113
+ ACTIVE = "a",
114
+ AT_RULE = "t",
115
+ KEYFRAME = "k",
116
+ FALLBACK = "c"
117
+ }
118
+ export interface CSSRule {
119
+ selector: string;
120
+ property: string;
121
+ value: string | number;
122
+ bucket: StyleBucket;
123
+ media?: string;
124
+ support?: string;
125
+ pseudo?: string;
126
+ }
127
+ export interface GeneratedClasses {
128
+ [key: string]: string;
129
+ }
130
+ export interface StyleSheet {
131
+ insertRule(rule: string, bucket: StyleBucket): void;
132
+ getRules(): string;
133
+ clearRules(): void;
134
+ }
135
+ export interface StyleEngineConfig {
136
+ styleSheet?: StyleSheet;
137
+ prefix?: string;
138
+ sourceMaps?: boolean;
139
+ }
140
+ export type MakeStylesFunction = () => GeneratedClasses;
141
+ export interface StyleSlots {
142
+ [slotName: string]: StyleDefinition;
143
+ }
package/dist/types.js ADDED
@@ -0,0 +1,15 @@
1
+ export var StyleBucket;
2
+ (function (StyleBucket) {
3
+ StyleBucket["RESET"] = "d";
4
+ StyleBucket["DEFAULT"] = "l";
5
+ StyleBucket["LINK"] = "v";
6
+ StyleBucket["VISITED"] = "w";
7
+ StyleBucket["FOCUS_VISIBLE"] = "f";
8
+ StyleBucket["FOCUS_WITHIN"] = "i";
9
+ StyleBucket["FOCUS"] = "o";
10
+ StyleBucket["HOVER"] = "h";
11
+ StyleBucket["ACTIVE"] = "a";
12
+ StyleBucket["AT_RULE"] = "t";
13
+ StyleBucket["KEYFRAME"] = "k";
14
+ StyleBucket["FALLBACK"] = "c";
15
+ })(StyleBucket || (StyleBucket = {}));
@@ -0,0 +1,2 @@
1
+ import { StyleBucket } from '../types';
2
+ export declare function determineBucket(pseudo?: string, media?: string): StyleBucket;
@@ -0,0 +1,27 @@
1
+ import { StyleBucket } from '../types';
2
+ export function determineBucket(pseudo, media) {
3
+ if (media) {
4
+ return StyleBucket.AT_RULE;
5
+ }
6
+ if (pseudo) {
7
+ switch (pseudo) {
8
+ case ':link':
9
+ return StyleBucket.LINK;
10
+ case ':visited':
11
+ return StyleBucket.VISITED;
12
+ case ':focus-visible':
13
+ return StyleBucket.FOCUS_VISIBLE;
14
+ case ':focus-within':
15
+ return StyleBucket.FOCUS_WITHIN;
16
+ case ':focus':
17
+ return StyleBucket.FOCUS;
18
+ case ':hover':
19
+ return StyleBucket.HOVER;
20
+ case ':active':
21
+ return StyleBucket.ACTIVE;
22
+ default:
23
+ return StyleBucket.DEFAULT;
24
+ }
25
+ }
26
+ return StyleBucket.DEFAULT;
27
+ }
@@ -0,0 +1,3 @@
1
+ export declare function camelToKebab(str: string): string;
2
+ export declare function isPseudoSelector(key: string): boolean;
3
+ export declare function isMediaQuery(key: string): boolean;
@@ -0,0 +1,9 @@
1
+ export function camelToKebab(str) {
2
+ return str.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
3
+ }
4
+ export function isPseudoSelector(key) {
5
+ return key.startsWith(':') || key.startsWith('::');
6
+ }
7
+ export function isMediaQuery(key) {
8
+ return key.startsWith('@media');
9
+ }
@@ -0,0 +1,2 @@
1
+ export declare function hashString(input: string): string;
2
+ export declare function createClassName(hashInput: string): string;
@@ -0,0 +1,10 @@
1
+ export function hashString(input) {
2
+ let hash = 5381;
3
+ for (let i = 0; i < input.length; i++) {
4
+ hash = (hash * 33) ^ input.charCodeAt(i);
5
+ }
6
+ return (hash >>> 0).toString(36);
7
+ }
8
+ export function createClassName(hashInput) {
9
+ return `f${hashString(hashInput)}`;
10
+ }
@@ -0,0 +1,3 @@
1
+ export { hashString } from './hash';
2
+ export { camelToKebab, isPseudoSelector, isMediaQuery } from './css';
3
+ export { determineBucket } from './bucket';
@@ -0,0 +1,3 @@
1
+ export { hashString } from './hash';
2
+ export { camelToKebab, isPseudoSelector, isMediaQuery } from './css';
3
+ export { determineBucket } from './bucket';
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "css-engine-test-pb",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.9.3"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ]
26
+ }