juxscript 1.1.112 → 1.1.113
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/css-classes-inventory.json +154 -2
- package/dom-structure-map.json +114 -2
- package/index.d.ts +4 -0
- package/index.d.ts.map +1 -1
- package/index.js +4 -0
- package/lib/components/base/LayoutExtensions.d.ts +6 -0
- package/lib/components/base/LayoutExtensions.d.ts.map +1 -1
- package/lib/components/base/LayoutExtensions.js +19 -0
- package/lib/components/base/LayoutExtensions.ts +29 -0
- package/lib/components/image.d.ts +42 -0
- package/lib/components/image.d.ts.map +1 -0
- package/lib/components/image.js +204 -0
- package/lib/components/image.ts +260 -0
- package/lib/components/layer.d.ts +72 -0
- package/lib/components/layer.d.ts.map +1 -0
- package/lib/components/layer.js +219 -0
- package/lib/components/layer.ts +304 -0
- package/lib/styles/gradients.css +326 -0
- package/package.json +1 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
// Event definitions
|
|
3
|
+
const TRIGGER_EVENTS = [];
|
|
4
|
+
const CALLBACK_EVENTS = [];
|
|
5
|
+
export class Layer extends BaseComponent {
|
|
6
|
+
constructor(id, options = {}) {
|
|
7
|
+
super(id, {
|
|
8
|
+
visible: true,
|
|
9
|
+
disabled: false,
|
|
10
|
+
loading: false,
|
|
11
|
+
class: options.class ?? '',
|
|
12
|
+
style: options.style ?? '',
|
|
13
|
+
attributes: {},
|
|
14
|
+
preset: options.preset,
|
|
15
|
+
content: typeof options.content === 'string' ? options.content : undefined
|
|
16
|
+
});
|
|
17
|
+
// Apply initial options via layout extensions
|
|
18
|
+
if (options.opacity !== undefined) {
|
|
19
|
+
this.opacity(options.opacity);
|
|
20
|
+
}
|
|
21
|
+
if (options.zIndex !== undefined) {
|
|
22
|
+
this.zIndex(options.zIndex);
|
|
23
|
+
}
|
|
24
|
+
if (options.blur !== undefined) {
|
|
25
|
+
this.backdropBlur(options.blur);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
getTriggerEvents() {
|
|
29
|
+
return TRIGGER_EVENTS;
|
|
30
|
+
}
|
|
31
|
+
getCallbackEvents() {
|
|
32
|
+
return CALLBACK_EVENTS;
|
|
33
|
+
}
|
|
34
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
35
|
+
* FLUENT API
|
|
36
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
37
|
+
/**
|
|
38
|
+
* Set layer opacity
|
|
39
|
+
*/
|
|
40
|
+
opacity(value) {
|
|
41
|
+
const opacityValue = Math.max(0, Math.min(1, value));
|
|
42
|
+
const currentStyle = this.state.style || '';
|
|
43
|
+
// Remove existing opacity
|
|
44
|
+
const styles = currentStyle
|
|
45
|
+
.split(';')
|
|
46
|
+
.filter(s => !s.trim().startsWith('opacity'))
|
|
47
|
+
.map(s => s.trim());
|
|
48
|
+
styles.push(`opacity: ${opacityValue}`);
|
|
49
|
+
this.state.style = styles.join('; ');
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Set layer z-index
|
|
54
|
+
*/
|
|
55
|
+
zIndex(value) {
|
|
56
|
+
const currentStyle = this.state.style || '';
|
|
57
|
+
// Remove existing z-index
|
|
58
|
+
const styles = currentStyle
|
|
59
|
+
.split(';')
|
|
60
|
+
.filter(s => !s.trim().startsWith('z-index'))
|
|
61
|
+
.map(s => s.trim());
|
|
62
|
+
styles.push(`z-index: ${value}`);
|
|
63
|
+
this.state.style = styles.join('; ');
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Apply a gradient preset from gradients.css
|
|
68
|
+
*/
|
|
69
|
+
preset(value) {
|
|
70
|
+
this.state.preset = value;
|
|
71
|
+
this.addClass(`jux-gradient-${value}`);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Set layer content (text or component)
|
|
76
|
+
*/
|
|
77
|
+
content(value) {
|
|
78
|
+
if (typeof value === 'string') {
|
|
79
|
+
this.state.content = value;
|
|
80
|
+
if (this.container) {
|
|
81
|
+
const el = this.container.querySelector(`#${this._id}`);
|
|
82
|
+
if (el)
|
|
83
|
+
el.innerHTML = value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Apply backdrop blur (for overlay effects)
|
|
90
|
+
*/
|
|
91
|
+
backdropBlur(value) {
|
|
92
|
+
const blurValue = `blur(${value}px)`;
|
|
93
|
+
const currentStyle = this.state.style || '';
|
|
94
|
+
// Remove existing backdrop-filter
|
|
95
|
+
const styles = currentStyle
|
|
96
|
+
.split(';')
|
|
97
|
+
.filter(s => !s.trim().startsWith('backdrop-filter'))
|
|
98
|
+
.map(s => s.trim());
|
|
99
|
+
styles.push(`backdrop-filter: ${blurValue}`);
|
|
100
|
+
this.state.style = styles.join('; ');
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Make layer cover entire parent (position: absolute with inset: 0)
|
|
105
|
+
*/
|
|
106
|
+
fullCover() {
|
|
107
|
+
const currentStyle = this.state.style || '';
|
|
108
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
109
|
+
styles.push('position: absolute', 'top: 0', 'left: 0', 'right: 0', 'bottom: 0');
|
|
110
|
+
this.state.style = styles.join('; ');
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Make layer fixed to viewport
|
|
115
|
+
*/
|
|
116
|
+
fixed() {
|
|
117
|
+
const currentStyle = this.state.style || '';
|
|
118
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
119
|
+
styles.push('position: fixed', 'top: 0', 'left: 0', 'right: 0', 'bottom: 0');
|
|
120
|
+
this.state.style = styles.join('; ');
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
124
|
+
* RENDER
|
|
125
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
126
|
+
render(targetId) {
|
|
127
|
+
const container = this._setupContainer(targetId);
|
|
128
|
+
const { preset, content, style, class: className } = this.state;
|
|
129
|
+
const layer = document.createElement('div');
|
|
130
|
+
layer.id = this._id;
|
|
131
|
+
layer.className = 'jux-layer';
|
|
132
|
+
if (preset) {
|
|
133
|
+
layer.className += ` jux-gradient-${preset}`;
|
|
134
|
+
}
|
|
135
|
+
if (className) {
|
|
136
|
+
layer.className += ` ${className}`;
|
|
137
|
+
}
|
|
138
|
+
if (style) {
|
|
139
|
+
layer.setAttribute('style', style);
|
|
140
|
+
}
|
|
141
|
+
if (content) {
|
|
142
|
+
layer.innerHTML = content;
|
|
143
|
+
}
|
|
144
|
+
this._wireStandardEvents(layer);
|
|
145
|
+
container.appendChild(layer);
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
update(prop, value) {
|
|
149
|
+
if (!this.container)
|
|
150
|
+
return;
|
|
151
|
+
const el = this.container.querySelector(`#${this._id}`);
|
|
152
|
+
if (!el)
|
|
153
|
+
return;
|
|
154
|
+
switch (prop) {
|
|
155
|
+
case 'preset':
|
|
156
|
+
// Remove old gradient classes
|
|
157
|
+
el.className = el.className
|
|
158
|
+
.split(' ')
|
|
159
|
+
.filter(c => !c.startsWith('jux-gradient-'))
|
|
160
|
+
.join(' ');
|
|
161
|
+
// Add new gradient class
|
|
162
|
+
if (value) {
|
|
163
|
+
el.classList.add(`jux-gradient-${value}`);
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
case 'content':
|
|
167
|
+
el.innerHTML = value;
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
super.update(prop, value);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export function layer(id, options = {}) {
|
|
176
|
+
return new Layer(id, options);
|
|
177
|
+
}
|
|
178
|
+
// ✅ Convenience helpers for common use cases
|
|
179
|
+
/**
|
|
180
|
+
* Create a gradient layer with preset
|
|
181
|
+
*/
|
|
182
|
+
export function gradient(id, preset, options = {}) {
|
|
183
|
+
return new Layer(id, { ...options, preset });
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Create a dark overlay (for hero images, etc.)
|
|
187
|
+
*/
|
|
188
|
+
export function overlay(id, opacity = 0.5) {
|
|
189
|
+
const layer = new Layer(id, { preset: 'overlay-dark', opacity }).fullCover();
|
|
190
|
+
const currentStyle = layer.state.style || '';
|
|
191
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
192
|
+
styles.push('pointer-events: none');
|
|
193
|
+
layer.state.style = styles.join('; ');
|
|
194
|
+
return layer;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Create a blur overlay (glassmorphism effect)
|
|
198
|
+
*/
|
|
199
|
+
export function glassLayer(id, blur = 10, opacity = 0.8) {
|
|
200
|
+
const layer = new Layer(id, { blur, opacity }).fullCover();
|
|
201
|
+
const currentStyle = layer.state.style || '';
|
|
202
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
203
|
+
styles.push('background-color: rgba(255, 255, 255, 0.1)');
|
|
204
|
+
layer.state.style = styles.join('; ');
|
|
205
|
+
return layer;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Create an animated gradient background
|
|
209
|
+
*/
|
|
210
|
+
export function animatedGradient(id, speed = 'normal') {
|
|
211
|
+
const presetMap = {
|
|
212
|
+
fast: 'animated-fast',
|
|
213
|
+
normal: 'animated',
|
|
214
|
+
slow: 'animated-slow'
|
|
215
|
+
};
|
|
216
|
+
return new Layer(id, { preset: presetMap[speed] })
|
|
217
|
+
.fullCover()
|
|
218
|
+
.zIndex(-1);
|
|
219
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { BaseComponent, BaseState } from './base/BaseComponent.js';
|
|
2
|
+
|
|
3
|
+
// Event definitions
|
|
4
|
+
const TRIGGER_EVENTS = [] as const;
|
|
5
|
+
const CALLBACK_EVENTS = [] as const;
|
|
6
|
+
|
|
7
|
+
export interface LayerOptions {
|
|
8
|
+
preset?: LayerPreset;
|
|
9
|
+
opacity?: number;
|
|
10
|
+
zIndex?: number;
|
|
11
|
+
blur?: number;
|
|
12
|
+
content?: string | BaseComponent<any>;
|
|
13
|
+
style?: string;
|
|
14
|
+
class?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface LayerState extends BaseState {
|
|
18
|
+
preset?: string;
|
|
19
|
+
content?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Gradient preset names from gradients.css
|
|
24
|
+
*/
|
|
25
|
+
export type LayerPreset =
|
|
26
|
+
// Linear Gradients
|
|
27
|
+
| 'ocean' | 'sunset' | 'forest' | 'fire' | 'ice' | 'candy' | 'emerald'
|
|
28
|
+
| 'midnight' | 'peach' | 'royal' | 'coral' | 'mint' | 'grape' | 'cherry' | 'sky'
|
|
29
|
+
// Multi-Stop Linear
|
|
30
|
+
| 'aurora' | 'tropical' | 'cosmic' | 'neon' | 'volcano'
|
|
31
|
+
// Radial Gradients
|
|
32
|
+
| 'radial-sun' | 'radial-moon' | 'radial-blue' | 'radial-purple'
|
|
33
|
+
| 'radial-fire' | 'radial-ocean' | 'radial-emerald' | 'radial-sunset'
|
|
34
|
+
// Conic Gradients
|
|
35
|
+
| 'conic-rainbow' | 'conic-sunset' | 'conic-ocean' | 'conic-fire' | 'conic-neon'
|
|
36
|
+
// Dark Gradients
|
|
37
|
+
| 'dark-space' | 'dark-navy' | 'dark-purple' | 'dark-forest'
|
|
38
|
+
| 'dark-crimson' | 'dark-slate'
|
|
39
|
+
// Transparent Overlays
|
|
40
|
+
| 'overlay-dark' | 'overlay-light' | 'overlay-blue' | 'overlay-purple' | 'overlay-sunset'
|
|
41
|
+
// Mesh/Textured
|
|
42
|
+
| 'mesh-purple' | 'mesh-ocean' | 'mesh-fire' | 'mesh-neon'
|
|
43
|
+
// Pastel
|
|
44
|
+
| 'pastel-pink' | 'pastel-blue' | 'pastel-green' | 'pastel-purple'
|
|
45
|
+
| 'pastel-peach' | 'pastel-lavender'
|
|
46
|
+
// Animated
|
|
47
|
+
| 'animated' | 'animated-fast' | 'animated-slow';
|
|
48
|
+
|
|
49
|
+
export class Layer extends BaseComponent<LayerState> {
|
|
50
|
+
constructor(id: string, options: LayerOptions = {}) {
|
|
51
|
+
super(id, {
|
|
52
|
+
visible: true,
|
|
53
|
+
disabled: false,
|
|
54
|
+
loading: false,
|
|
55
|
+
class: options.class ?? '',
|
|
56
|
+
style: options.style ?? '',
|
|
57
|
+
attributes: {},
|
|
58
|
+
preset: options.preset,
|
|
59
|
+
content: typeof options.content === 'string' ? options.content : undefined
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Apply initial options via layout extensions
|
|
63
|
+
if (options.opacity !== undefined) {
|
|
64
|
+
this.opacity(options.opacity);
|
|
65
|
+
}
|
|
66
|
+
if (options.zIndex !== undefined) {
|
|
67
|
+
this.zIndex(options.zIndex);
|
|
68
|
+
}
|
|
69
|
+
if (options.blur !== undefined) {
|
|
70
|
+
this.backdropBlur(options.blur);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
protected getTriggerEvents(): readonly string[] {
|
|
75
|
+
return TRIGGER_EVENTS;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
protected getCallbackEvents(): readonly string[] {
|
|
79
|
+
return CALLBACK_EVENTS;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
83
|
+
* FLUENT API
|
|
84
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Set layer opacity
|
|
88
|
+
*/
|
|
89
|
+
opacity(value: number): this {
|
|
90
|
+
const opacityValue = Math.max(0, Math.min(1, value));
|
|
91
|
+
const currentStyle = this.state.style || '';
|
|
92
|
+
|
|
93
|
+
// Remove existing opacity
|
|
94
|
+
const styles = currentStyle
|
|
95
|
+
.split(';')
|
|
96
|
+
.filter(s => !s.trim().startsWith('opacity'))
|
|
97
|
+
.map(s => s.trim());
|
|
98
|
+
|
|
99
|
+
styles.push(`opacity: ${opacityValue}`);
|
|
100
|
+
this.state.style = styles.join('; ');
|
|
101
|
+
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Set layer z-index
|
|
107
|
+
*/
|
|
108
|
+
zIndex(value: number): this {
|
|
109
|
+
const currentStyle = this.state.style || '';
|
|
110
|
+
|
|
111
|
+
// Remove existing z-index
|
|
112
|
+
const styles = currentStyle
|
|
113
|
+
.split(';')
|
|
114
|
+
.filter(s => !s.trim().startsWith('z-index'))
|
|
115
|
+
.map(s => s.trim());
|
|
116
|
+
|
|
117
|
+
styles.push(`z-index: ${value}`);
|
|
118
|
+
this.state.style = styles.join('; ');
|
|
119
|
+
|
|
120
|
+
return this;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Apply a gradient preset from gradients.css
|
|
125
|
+
*/
|
|
126
|
+
preset(value: LayerPreset): this {
|
|
127
|
+
this.state.preset = value;
|
|
128
|
+
this.addClass(`jux-gradient-${value}`);
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Set layer content (text or component)
|
|
134
|
+
*/
|
|
135
|
+
content(value: string | BaseComponent<any>): this {
|
|
136
|
+
if (typeof value === 'string') {
|
|
137
|
+
this.state.content = value;
|
|
138
|
+
if (this.container) {
|
|
139
|
+
const el = this.container.querySelector(`#${this._id}`) as HTMLElement;
|
|
140
|
+
if (el) el.innerHTML = value;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Apply backdrop blur (for overlay effects)
|
|
148
|
+
*/
|
|
149
|
+
backdropBlur(value: number): this {
|
|
150
|
+
const blurValue = `blur(${value}px)`;
|
|
151
|
+
const currentStyle = this.state.style || '';
|
|
152
|
+
|
|
153
|
+
// Remove existing backdrop-filter
|
|
154
|
+
const styles = currentStyle
|
|
155
|
+
.split(';')
|
|
156
|
+
.filter(s => !s.trim().startsWith('backdrop-filter'))
|
|
157
|
+
.map(s => s.trim());
|
|
158
|
+
|
|
159
|
+
styles.push(`backdrop-filter: ${blurValue}`);
|
|
160
|
+
this.state.style = styles.join('; ');
|
|
161
|
+
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Make layer cover entire parent (position: absolute with inset: 0)
|
|
167
|
+
*/
|
|
168
|
+
fullCover(): this {
|
|
169
|
+
const currentStyle = this.state.style || '';
|
|
170
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
171
|
+
styles.push('position: absolute', 'top: 0', 'left: 0', 'right: 0', 'bottom: 0');
|
|
172
|
+
this.state.style = styles.join('; ');
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Make layer fixed to viewport
|
|
178
|
+
*/
|
|
179
|
+
fixed(): this {
|
|
180
|
+
const currentStyle = this.state.style || '';
|
|
181
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
182
|
+
styles.push('position: fixed', 'top: 0', 'left: 0', 'right: 0', 'bottom: 0');
|
|
183
|
+
this.state.style = styles.join('; ');
|
|
184
|
+
return this;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
188
|
+
* RENDER
|
|
189
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
190
|
+
|
|
191
|
+
render(targetId?: string | HTMLElement | BaseComponent<any>): this {
|
|
192
|
+
const container = this._setupContainer(targetId);
|
|
193
|
+
|
|
194
|
+
const { preset, content, style, class: className } = this.state;
|
|
195
|
+
|
|
196
|
+
const layer = document.createElement('div');
|
|
197
|
+
layer.id = this._id;
|
|
198
|
+
layer.className = 'jux-layer';
|
|
199
|
+
|
|
200
|
+
if (preset) {
|
|
201
|
+
layer.className += ` jux-gradient-${preset}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (className) {
|
|
205
|
+
layer.className += ` ${className}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (style) {
|
|
209
|
+
layer.setAttribute('style', style);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (content) {
|
|
213
|
+
layer.innerHTML = content;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this._wireStandardEvents(layer);
|
|
217
|
+
|
|
218
|
+
container.appendChild(layer);
|
|
219
|
+
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
update(prop: string, value: any): void {
|
|
224
|
+
if (!this.container) return;
|
|
225
|
+
|
|
226
|
+
const el = this.container.querySelector(`#${this._id}`) as HTMLElement;
|
|
227
|
+
if (!el) return;
|
|
228
|
+
|
|
229
|
+
switch (prop) {
|
|
230
|
+
case 'preset':
|
|
231
|
+
// Remove old gradient classes
|
|
232
|
+
el.className = el.className
|
|
233
|
+
.split(' ')
|
|
234
|
+
.filter(c => !c.startsWith('jux-gradient-'))
|
|
235
|
+
.join(' ');
|
|
236
|
+
|
|
237
|
+
// Add new gradient class
|
|
238
|
+
if (value) {
|
|
239
|
+
el.classList.add(`jux-gradient-${value}`);
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
|
|
243
|
+
case 'content':
|
|
244
|
+
el.innerHTML = value;
|
|
245
|
+
break;
|
|
246
|
+
|
|
247
|
+
default:
|
|
248
|
+
super.update(prop, value);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function layer(id: string, options: LayerOptions = {}): Layer {
|
|
255
|
+
return new Layer(id, options);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ✅ Convenience helpers for common use cases
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Create a gradient layer with preset
|
|
262
|
+
*/
|
|
263
|
+
export function gradient(id: string, preset: LayerPreset, options: Omit<LayerOptions, 'preset'> = {}): Layer {
|
|
264
|
+
return new Layer(id, { ...options, preset });
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Create a dark overlay (for hero images, etc.)
|
|
269
|
+
*/
|
|
270
|
+
export function overlay(id: string, opacity: number = 0.5): Layer {
|
|
271
|
+
const layer = new Layer(id, { preset: 'overlay-dark', opacity }).fullCover();
|
|
272
|
+
const currentStyle = layer.state.style || '';
|
|
273
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
274
|
+
styles.push('pointer-events: none');
|
|
275
|
+
layer.state.style = styles.join('; ');
|
|
276
|
+
return layer;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Create a blur overlay (glassmorphism effect)
|
|
281
|
+
*/
|
|
282
|
+
export function glassLayer(id: string, blur: number = 10, opacity: number = 0.8): Layer {
|
|
283
|
+
const layer = new Layer(id, { blur, opacity }).fullCover();
|
|
284
|
+
const currentStyle = layer.state.style || '';
|
|
285
|
+
const styles = currentStyle.split(';').map(s => s.trim()).filter(Boolean);
|
|
286
|
+
styles.push('background-color: rgba(255, 255, 255, 0.1)');
|
|
287
|
+
layer.state.style = styles.join('; ');
|
|
288
|
+
return layer;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Create an animated gradient background
|
|
293
|
+
*/
|
|
294
|
+
export function animatedGradient(id: string, speed: 'fast' | 'normal' | 'slow' = 'normal'): Layer {
|
|
295
|
+
const presetMap = {
|
|
296
|
+
fast: 'animated-fast' as LayerPreset,
|
|
297
|
+
normal: 'animated' as LayerPreset,
|
|
298
|
+
slow: 'animated-slow' as LayerPreset
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
return new Layer(id, { preset: presetMap[speed] })
|
|
302
|
+
.fullCover()
|
|
303
|
+
.zIndex(-1);
|
|
304
|
+
}
|