@v-ibe/core 0.1.0 → 0.1.2

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.
@@ -278,12 +278,12 @@ class BaseComponent extends HTMLElement {
278
278
  );
279
279
  if (metadata?.stylesClass) {
280
280
  const stylesInstance = new metadata.stylesClass();
281
+ stylesInstance.setHost(this);
281
282
  const stylesheet = stylesInstance.getStyleSheet();
282
283
  this.shadowRoot.adoptedStyleSheets = [
283
284
  ...this.shadowRoot.adoptedStyleSheets,
284
285
  stylesheet
285
286
  ];
286
- stylesInstance.setHost(this);
287
287
  }
288
288
  }
289
289
  initializeContexts() {
package/dist/index.d.ts CHANGED
@@ -33,7 +33,7 @@ export { registerServiceMetadata, getServiceMetadata, getAllServiceMetadata, cle
33
33
  export type { ServiceMetadata } from './DI/service-metadata';
34
34
  export { core } from './core';
35
35
  export { Rule } from './styles/decorators/rule';
36
- export type { CSSProperties } from './styles/decorators/rule';
36
+ export type { CSSProperties } from './styles/css-properties';
37
37
  export { UseStyles } from './styles/decorators/useStyles';
38
38
  export { Behavior, Host, ComponentHost } from './behaviors';
39
39
  export { MediaQuery } from './styles/decorators/factories';
@@ -0,0 +1 @@
1
+ export {};
@@ -30,12 +30,19 @@ export declare class BaseStyleSheet {
30
30
  index: number;
31
31
  effect: any;
32
32
  }>;
33
+ private _rulesActivated;
33
34
  constructor();
34
35
  /**
35
- * Returns the internal CSSStyleSheet
36
- * Used by @UseStyles decorator to attach styles to components
36
+ * Returns the internal CSSStyleSheet.
37
+ * If no @Host is used, activates @Rule effects on first call.
38
+ * If @Host is used, effects are activated by setHost() instead.
37
39
  */
38
40
  getStyleSheet(): CSSStyleSheet;
41
+ /**
42
+ * Reads @Rule definitions from the constructor and creates reactive effects
43
+ * for each rule getter. Only runs once per instance.
44
+ */
45
+ private activateRules;
39
46
  /**
40
47
  * Sets the host component and initializes styles
41
48
  * Called by @UseStyles decorator when attaching styles to a component
@@ -1,20 +1,49 @@
1
1
  import { HOST_KEY } from "../behaviors/constants.js";
2
+ import { effect } from "../reactivity/signals/effect.js";
3
+ import { RULES_KEY, cssObjectToString } from "./decorators/rule.js";
2
4
  class BaseStyleSheet {
3
5
  constructor() {
4
6
  this.cleanupFunctions = [];
5
7
  this.selectorSymbolMap = /* @__PURE__ */ new Map();
6
8
  this.documentStyleElement = null;
7
9
  this.documentRuleMap = /* @__PURE__ */ new Map();
10
+ this._rulesActivated = false;
8
11
  this.stylesheet = new CSSStyleSheet();
9
12
  this.ruleIndexMap = /* @__PURE__ */ new Map();
10
13
  }
11
14
  /**
12
- * Returns the internal CSSStyleSheet
13
- * Used by @UseStyles decorator to attach styles to components
15
+ * Returns the internal CSSStyleSheet.
16
+ * If no @Host is used, activates @Rule effects on first call.
17
+ * If @Host is used, effects are activated by setHost() instead.
14
18
  */
15
19
  getStyleSheet() {
20
+ this.activateRules();
16
21
  return this.stylesheet;
17
22
  }
23
+ /**
24
+ * Reads @Rule definitions from the constructor and creates reactive effects
25
+ * for each rule getter. Only runs once per instance.
26
+ */
27
+ activateRules() {
28
+ if (this._rulesActivated) return;
29
+ this._rulesActivated = true;
30
+ const rules = this.constructor[RULES_KEY];
31
+ if (!rules) return;
32
+ for (const { selector, getterName, getter } of rules) {
33
+ const indexSymbol = Symbol(`css_rule_${selector}_${getterName}`);
34
+ const cleanup = effect(() => {
35
+ const stylesObject = getter.call(this);
36
+ if (!stylesObject || typeof stylesObject !== "object") {
37
+ console.warn(`@Rule('${selector}'): Getter '${getterName}' must return a CSSProperties object`);
38
+ return;
39
+ }
40
+ const cssContent = cssObjectToString(stylesObject);
41
+ const cssText = `${selector} { ${cssContent}; }`;
42
+ this.updateSpecificRule(selector, cssText, indexSymbol);
43
+ });
44
+ this.registerCleanup(cleanup.dispose);
45
+ }
46
+ }
18
47
  /**
19
48
  * Sets the host component and initializes styles
20
49
  * Called by @UseStyles decorator when attaching styles to a component
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Comprehensive CSS Properties Interface
3
+ * Provides type safety and autocomplete for CSS declarations
4
+ */
5
+ export interface CSSProperties {
6
+ display?: 'block' | 'inline' | 'inline-block' | 'flex' | 'inline-flex' | 'grid' | 'inline-grid' | 'none' | 'contents' | 'table' | 'table-row' | 'table-cell' | string;
7
+ visibility?: 'visible' | 'hidden' | 'collapse';
8
+ opacity?: number | string;
9
+ position?: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky';
10
+ top?: number | string;
11
+ right?: number | string;
12
+ bottom?: number | string;
13
+ left?: number | string;
14
+ inset?: number | string;
15
+ zIndex?: number | string;
16
+ flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
17
+ flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
18
+ justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch';
19
+ alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
20
+ alignContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'stretch';
21
+ gap?: number | string;
22
+ rowGap?: number | string;
23
+ columnGap?: number | string;
24
+ flex?: number | string;
25
+ flexGrow?: number;
26
+ flexShrink?: number;
27
+ flexBasis?: number | string;
28
+ alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
29
+ order?: number;
30
+ gridTemplateColumns?: string;
31
+ gridTemplateRows?: string;
32
+ gridTemplateAreas?: string;
33
+ gridAutoColumns?: string;
34
+ gridAutoRows?: string;
35
+ gridAutoFlow?: 'row' | 'column' | 'dense' | 'row dense' | 'column dense';
36
+ gridArea?: string;
37
+ gridColumn?: string;
38
+ gridRow?: string;
39
+ gridColumnStart?: string | number;
40
+ gridColumnEnd?: string | number;
41
+ gridRowStart?: string | number;
42
+ gridRowEnd?: string | number;
43
+ width?: number | string;
44
+ height?: number | string;
45
+ minWidth?: number | string;
46
+ maxWidth?: number | string;
47
+ minHeight?: number | string;
48
+ maxHeight?: number | string;
49
+ boxSizing?: 'content-box' | 'border-box';
50
+ margin?: number | string;
51
+ marginTop?: number | string;
52
+ marginRight?: number | string;
53
+ marginBottom?: number | string;
54
+ marginLeft?: number | string;
55
+ marginBlock?: number | string;
56
+ marginInline?: number | string;
57
+ padding?: number | string;
58
+ paddingTop?: number | string;
59
+ paddingRight?: number | string;
60
+ paddingBottom?: number | string;
61
+ paddingLeft?: number | string;
62
+ paddingBlock?: number | string;
63
+ paddingInline?: number | string;
64
+ color?: string;
65
+ fontSize?: number | string;
66
+ fontFamily?: string;
67
+ fontWeight?: number | 'normal' | 'bold' | 'lighter' | 'bolder' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
68
+ fontStyle?: 'normal' | 'italic' | 'oblique';
69
+ lineHeight?: number | string;
70
+ letterSpacing?: number | string;
71
+ textAlign?: 'left' | 'right' | 'center' | 'justify' | 'start' | 'end';
72
+ textDecoration?: string;
73
+ textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
74
+ textOverflow?: 'clip' | 'ellipsis' | string;
75
+ whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-wrap' | 'pre-line' | 'break-spaces';
76
+ wordBreak?: 'normal' | 'break-all' | 'keep-all' | 'break-word';
77
+ wordWrap?: 'normal' | 'break-word';
78
+ background?: string;
79
+ backgroundColor?: string;
80
+ backgroundImage?: string;
81
+ backgroundSize?: string;
82
+ backgroundPosition?: string;
83
+ backgroundRepeat?: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat' | 'space' | 'round';
84
+ backgroundAttachment?: 'scroll' | 'fixed' | 'local';
85
+ backgroundClip?: 'border-box' | 'padding-box' | 'content-box' | 'text';
86
+ border?: string;
87
+ borderWidth?: number | string;
88
+ borderStyle?: 'none' | 'solid' | 'dashed' | 'dotted' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
89
+ borderColor?: string;
90
+ borderRadius?: number | string;
91
+ borderTop?: string;
92
+ borderRight?: string;
93
+ borderBottom?: string;
94
+ borderLeft?: string;
95
+ borderTopWidth?: number | string;
96
+ borderRightWidth?: number | string;
97
+ borderBottomWidth?: number | string;
98
+ borderLeftWidth?: number | string;
99
+ borderTopColor?: string;
100
+ borderRightColor?: string;
101
+ borderBottomColor?: string;
102
+ borderLeftColor?: string;
103
+ borderTopLeftRadius?: number | string;
104
+ borderTopRightRadius?: number | string;
105
+ borderBottomLeftRadius?: number | string;
106
+ borderBottomRightRadius?: number | string;
107
+ outline?: string;
108
+ outlineWidth?: number | string;
109
+ outlineStyle?: 'none' | 'solid' | 'dashed' | 'dotted' | 'double';
110
+ outlineColor?: string;
111
+ outlineOffset?: number | string;
112
+ boxShadow?: string;
113
+ textShadow?: string;
114
+ filter?: string;
115
+ backdropFilter?: string;
116
+ transform?: string;
117
+ transformOrigin?: string;
118
+ transition?: string;
119
+ transitionProperty?: string;
120
+ transitionDuration?: string;
121
+ transitionTimingFunction?: string;
122
+ transitionDelay?: string;
123
+ animation?: string;
124
+ animationName?: string;
125
+ animationDuration?: string;
126
+ animationTimingFunction?: string;
127
+ animationDelay?: string;
128
+ animationIterationCount?: number | 'infinite';
129
+ animationDirection?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
130
+ animationFillMode?: 'none' | 'forwards' | 'backwards' | 'both';
131
+ animationPlayState?: 'running' | 'paused';
132
+ overflow?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
133
+ overflowX?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
134
+ overflowY?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
135
+ clip?: string;
136
+ clipPath?: string;
137
+ cursor?: 'auto' | 'default' | 'pointer' | 'wait' | 'text' | 'move' | 'not-allowed' | 'help' | 'grab' | 'grabbing' | string;
138
+ pointerEvents?: 'auto' | 'none' | 'visiblePainted' | 'visibleFill' | 'visibleStroke' | 'visible' | 'painted' | 'fill' | 'stroke' | 'all';
139
+ userSelect?: 'none' | 'auto' | 'text' | 'contain' | 'all';
140
+ content?: string;
141
+ listStyle?: string;
142
+ listStyleType?: string;
143
+ listStylePosition?: 'inside' | 'outside';
144
+ listStyleImage?: string;
145
+ tableLayout?: 'auto' | 'fixed';
146
+ borderCollapse?: 'collapse' | 'separate';
147
+ borderSpacing?: number | string;
148
+ captionSide?: 'top' | 'bottom';
149
+ emptyCells?: 'show' | 'hide';
150
+ verticalAlign?: 'baseline' | 'sub' | 'super' | 'top' | 'text-top' | 'middle' | 'bottom' | 'text-bottom' | number | string;
151
+ objectFit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
152
+ objectPosition?: string;
153
+ float?: 'none' | 'left' | 'right';
154
+ clear?: 'none' | 'left' | 'right' | 'both';
155
+ resize?: 'none' | 'both' | 'horizontal' | 'vertical';
156
+ [key: `--${string}`]: string | number;
157
+ [key: string]: any;
158
+ }
@@ -1,163 +1,41 @@
1
+ import { CSSProperties } from '../css-properties';
2
+ export type { CSSProperties };
1
3
  /**
2
- * Comprehensive CSS Properties Interface
3
- * Provides type safety and autocomplete for CSS declarations
4
+ * Symbol to store rule definitions in class metadata.
5
+ * Each @Rule registers { selector, getterName, getter } in metadata[RULES_KEY].
4
6
  */
5
- export interface CSSProperties {
6
- display?: 'block' | 'inline' | 'inline-block' | 'flex' | 'inline-flex' | 'grid' | 'inline-grid' | 'none' | 'contents' | 'table' | 'table-row' | 'table-cell' | string;
7
- visibility?: 'visible' | 'hidden' | 'collapse';
8
- opacity?: number | string;
9
- position?: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky';
10
- top?: number | string;
11
- right?: number | string;
12
- bottom?: number | string;
13
- left?: number | string;
14
- inset?: number | string;
15
- zIndex?: number | string;
16
- flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
17
- flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
18
- justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch';
19
- alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
20
- alignContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'stretch';
21
- gap?: number | string;
22
- rowGap?: number | string;
23
- columnGap?: number | string;
24
- flex?: number | string;
25
- flexGrow?: number;
26
- flexShrink?: number;
27
- flexBasis?: number | string;
28
- alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
29
- order?: number;
30
- gridTemplateColumns?: string;
31
- gridTemplateRows?: string;
32
- gridTemplateAreas?: string;
33
- gridAutoColumns?: string;
34
- gridAutoRows?: string;
35
- gridAutoFlow?: 'row' | 'column' | 'dense' | 'row dense' | 'column dense';
36
- gridArea?: string;
37
- gridColumn?: string;
38
- gridRow?: string;
39
- gridColumnStart?: string | number;
40
- gridColumnEnd?: string | number;
41
- gridRowStart?: string | number;
42
- gridRowEnd?: string | number;
43
- width?: number | string;
44
- height?: number | string;
45
- minWidth?: number | string;
46
- maxWidth?: number | string;
47
- minHeight?: number | string;
48
- maxHeight?: number | string;
49
- boxSizing?: 'content-box' | 'border-box';
50
- margin?: number | string;
51
- marginTop?: number | string;
52
- marginRight?: number | string;
53
- marginBottom?: number | string;
54
- marginLeft?: number | string;
55
- marginBlock?: number | string;
56
- marginInline?: number | string;
57
- padding?: number | string;
58
- paddingTop?: number | string;
59
- paddingRight?: number | string;
60
- paddingBottom?: number | string;
61
- paddingLeft?: number | string;
62
- paddingBlock?: number | string;
63
- paddingInline?: number | string;
64
- color?: string;
65
- fontSize?: number | string;
66
- fontFamily?: string;
67
- fontWeight?: number | 'normal' | 'bold' | 'lighter' | 'bolder' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
68
- fontStyle?: 'normal' | 'italic' | 'oblique';
69
- lineHeight?: number | string;
70
- letterSpacing?: number | string;
71
- textAlign?: 'left' | 'right' | 'center' | 'justify' | 'start' | 'end';
72
- textDecoration?: string;
73
- textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
74
- textOverflow?: 'clip' | 'ellipsis' | string;
75
- whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-wrap' | 'pre-line' | 'break-spaces';
76
- wordBreak?: 'normal' | 'break-all' | 'keep-all' | 'break-word';
77
- wordWrap?: 'normal' | 'break-word';
78
- background?: string;
79
- backgroundColor?: string;
80
- backgroundImage?: string;
81
- backgroundSize?: string;
82
- backgroundPosition?: string;
83
- backgroundRepeat?: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat' | 'space' | 'round';
84
- backgroundAttachment?: 'scroll' | 'fixed' | 'local';
85
- backgroundClip?: 'border-box' | 'padding-box' | 'content-box' | 'text';
86
- border?: string;
87
- borderWidth?: number | string;
88
- borderStyle?: 'none' | 'solid' | 'dashed' | 'dotted' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
89
- borderColor?: string;
90
- borderRadius?: number | string;
91
- borderTop?: string;
92
- borderRight?: string;
93
- borderBottom?: string;
94
- borderLeft?: string;
95
- borderTopWidth?: number | string;
96
- borderRightWidth?: number | string;
97
- borderBottomWidth?: number | string;
98
- borderLeftWidth?: number | string;
99
- borderTopColor?: string;
100
- borderRightColor?: string;
101
- borderBottomColor?: string;
102
- borderLeftColor?: string;
103
- borderTopLeftRadius?: number | string;
104
- borderTopRightRadius?: number | string;
105
- borderBottomLeftRadius?: number | string;
106
- borderBottomRightRadius?: number | string;
107
- outline?: string;
108
- outlineWidth?: number | string;
109
- outlineStyle?: 'none' | 'solid' | 'dashed' | 'dotted' | 'double';
110
- outlineColor?: string;
111
- outlineOffset?: number | string;
112
- boxShadow?: string;
113
- textShadow?: string;
114
- filter?: string;
115
- backdropFilter?: string;
116
- transform?: string;
117
- transformOrigin?: string;
118
- transition?: string;
119
- transitionProperty?: string;
120
- transitionDuration?: string;
121
- transitionTimingFunction?: string;
122
- transitionDelay?: string;
123
- animation?: string;
124
- animationName?: string;
125
- animationDuration?: string;
126
- animationTimingFunction?: string;
127
- animationDelay?: string;
128
- animationIterationCount?: number | 'infinite';
129
- animationDirection?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
130
- animationFillMode?: 'none' | 'forwards' | 'backwards' | 'both';
131
- animationPlayState?: 'running' | 'paused';
132
- overflow?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
133
- overflowX?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
134
- overflowY?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
135
- clip?: string;
136
- clipPath?: string;
137
- cursor?: 'auto' | 'default' | 'pointer' | 'wait' | 'text' | 'move' | 'not-allowed' | 'help' | 'grab' | 'grabbing' | string;
138
- pointerEvents?: 'auto' | 'none' | 'visiblePainted' | 'visibleFill' | 'visibleStroke' | 'visible' | 'painted' | 'fill' | 'stroke' | 'all';
139
- userSelect?: 'none' | 'auto' | 'text' | 'contain' | 'all';
140
- content?: string;
141
- listStyle?: string;
142
- listStyleType?: string;
143
- listStylePosition?: 'inside' | 'outside';
144
- listStyleImage?: string;
145
- tableLayout?: 'auto' | 'fixed';
146
- borderCollapse?: 'collapse' | 'separate';
147
- borderSpacing?: number | string;
148
- captionSide?: 'top' | 'bottom';
149
- emptyCells?: 'show' | 'hide';
150
- verticalAlign?: 'baseline' | 'sub' | 'super' | 'top' | 'text-top' | 'middle' | 'bottom' | 'text-bottom' | number | string;
151
- objectFit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
152
- objectPosition?: string;
153
- float?: 'none' | 'left' | 'right';
154
- clear?: 'none' | 'left' | 'right' | 'both';
155
- resize?: 'none' | 'both' | 'horizontal' | 'vertical';
156
- [key: `--${string}`]: string | number;
157
- [key: string]: any;
7
+ export declare const RULES_KEY: unique symbol;
8
+ export interface RuleDefinition {
9
+ selector: string;
10
+ getterName: string;
11
+ getter: (this: any) => CSSProperties | undefined;
158
12
  }
159
13
  /**
160
- * @Rule Decorator - Type-safe reactive CSS rules
14
+ * Helper Functions for CSS Processing
15
+ */
16
+ /**
17
+ * Converts camelCase to kebab-case
18
+ * Example: backgroundColor → background-color
19
+ */
20
+ export declare function camelToKebab(str: string): string;
21
+ /**
22
+ * Formats a CSS value, adding units where necessary
23
+ * Example: ('width', 100) → '100px'
24
+ * ('opacity', 0.5) → '0.5'
25
+ */
26
+ export declare function formatCSSValue(property: string, value: any): string;
27
+ /**
28
+ * Converts a CSSProperties object to a CSS string
29
+ * Example: { width: 100, display: 'grid' } → 'width: 100px; display: grid'
30
+ */
31
+ export declare function cssObjectToString(styles: CSSProperties): string;
32
+ /**
33
+ * @Rule Decorator - Metadata-only marker for reactive CSS rules.
34
+ *
35
+ * Registers the getter and its CSS selector in class metadata.
36
+ * The actual reactive effects are created later by BaseStyleSheet
37
+ * when getStyleSheet() is called, ensuring @Host and all other
38
+ * fields are fully initialized before any effect runs.
161
39
  *
162
40
  * Usage:
163
41
  * ```typescript
@@ -165,7 +43,7 @@ export interface CSSProperties {
165
43
  * @State width = 100;
166
44
  *
167
45
  * @Rule(':host')
168
- * get hostStyles() {
46
+ * get hostStyles(): CSSProperties {
169
47
  * return {
170
48
  * display: 'grid',
171
49
  * width: this.width, // Reactive!
@@ -1,4 +1,4 @@
1
- import { effect } from "../../reactivity/signals/effect.js";
1
+ const RULES_KEY = Symbol("stylesheet:rules");
2
2
  function camelToKebab(str) {
3
3
  return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
4
4
  }
@@ -42,31 +42,27 @@ function Rule(selector) {
42
42
  throw new Error("@Rule can only be applied to getters");
43
43
  }
44
44
  const getterName = String(context.name);
45
+ const metadata = context.metadata;
46
+ if (!metadata[RULES_KEY]) {
47
+ metadata[RULES_KEY] = [];
48
+ }
49
+ metadata[RULES_KEY].push({
50
+ selector,
51
+ getterName,
52
+ getter: target
53
+ });
45
54
  context.addInitializer(function() {
46
- const indexSymbol = Symbol(`css_rule_${selector}_${getterName}`);
47
- const cleanup = effect(() => {
48
- const stylesObject = target.call(this);
49
- if (!stylesObject || typeof stylesObject !== "object") {
50
- console.warn(`@Rule('${selector}'): Getter '${getterName}' must return a CSSProperties object`);
51
- return;
52
- }
53
- const cssContent = cssObjectToString(stylesObject);
54
- const cssText = `${selector} { ${cssContent}; }`;
55
- if (typeof this.updateSpecificRule === "function") {
56
- this.updateSpecificRule(selector, cssText, indexSymbol);
57
- } else {
58
- console.error(`@Rule decorator requires BaseStyleSheet.updateSpecificRule method`);
59
- }
60
- });
61
- if (typeof this.registerCleanup === "function") {
62
- this.registerCleanup(cleanup.dispose);
63
- } else {
64
- console.error(`@Rule decorator requires BaseStyleSheet.registerCleanup method`);
55
+ if (!this.constructor[RULES_KEY]) {
56
+ this.constructor[RULES_KEY] = metadata[RULES_KEY];
65
57
  }
66
58
  });
67
59
  return target;
68
60
  };
69
61
  }
70
62
  export {
71
- Rule
63
+ RULES_KEY,
64
+ Rule,
65
+ camelToKebab,
66
+ cssObjectToString,
67
+ formatCSSValue
72
68
  };
@@ -11,6 +11,7 @@ function UseStyles(StylesConstructor) {
11
11
  try {
12
12
  const stylesInstance = new StylesConstructor();
13
13
  stylesInstance.setHost(this);
14
+ stylesInstance.getStyleSheet();
14
15
  Object.defineProperty(this, "styles", {
15
16
  value: stylesInstance,
16
17
  writable: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v-ibe/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A reactive framework for SPAs using signals, class-based web components, and JSX with direct DOM updates",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,8 @@
49
49
  "test": "vitest",
50
50
  "test:ui": "vitest --ui",
51
51
  "test:run": "vitest run",
52
- "test:coverage": "vitest run --coverage"
52
+ "test:coverage": "vitest run --coverage",
53
+ "docs": "hugo server --source docs"
53
54
  },
54
55
  "keywords": [
55
56
  "framework",
@@ -66,10 +67,12 @@
66
67
  "type": "git",
67
68
  "url": "git+https://github.com/arboledavargas/v-ibe.git"
68
69
  },
69
- "peerDependencies": {
70
- "typescript": ">=5.0.0",
70
+ "dependencies": {
71
71
  "vite": "^7.1.3"
72
72
  },
73
+ "peerDependencies": {
74
+ "typescript": ">=5.0.0"
75
+ },
73
76
  "devDependencies": {
74
77
  "@types/node": "^24.3.0",
75
78
  "@vitest/ui": "^4.0.17",