@shulya/liquid-glass 0.0.0-stage → 1.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.
- package/LICENSE +21 -0
- package/README.md +338 -2
- package/dist/angular.cjs +78 -0
- package/dist/angular.mjs +76 -0
- package/dist/core.cjs +1126 -0
- package/dist/core.mjs +1126 -0
- package/dist/index.cjs +17 -0
- package/dist/index.mjs +15 -0
- package/dist/react.cjs +105 -0
- package/dist/react.mjs +106 -0
- package/dist/solid.cjs +82 -0
- package/dist/solid.mjs +80 -0
- package/dist/svelte.cjs +29 -0
- package/dist/svelte.mjs +27 -0
- package/dist/tables.cjs +14 -0
- package/dist/tables.mjs +14 -0
- package/dist/vue.cjs +94 -0
- package/dist/vue.mjs +92 -0
- package/example/README.md +38 -0
- package/example/index.html +15 -0
- package/example/package.json +27 -0
- package/example/src/App.jsx +398 -0
- package/example/src/main.jsx +10 -0
- package/example/src/styles.css +158 -0
- package/example/vite.config.js +22 -0
- package/package.json +114 -4
- package/screen.png +0 -0
- package/src/angular.js +76 -0
- package/src/core.js +1126 -0
- package/src/index.js +15 -0
- package/src/react.js +106 -0
- package/src/solid.js +80 -0
- package/src/svelte.js +27 -0
- package/src/tables.js +14 -0
- package/src/vue.js +92 -0
- package/tables/optical_calibration_matrix.csv +257 -0
- package/tables/optical_calibration_matrix.xlsx +0 -0
- package/types/angular.d.ts +24 -0
- package/types/index.d.ts +80 -0
- package/types/react.d.ts +29 -0
- package/types/solid.d.ts +14 -0
- package/types/svelte.d.ts +15 -0
- package/types/vue.d.ts +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shulya LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,339 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@shulya/liquid-glass`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@shulya/liquid-glass)
|
|
4
|
+
[](https://liquid.shulya.tech)
|
|
5
|
+
[](https://github.com/shulya-tech/liquid-glass)
|
|
6
|
+
[-30d158?style=flat-square>)](#why-shulyaliquid-glass)
|
|
7
|
+
[](#framework-integrations)
|
|
8
|
+
[](https://github.com/shulya-tech/liquid-glass/blob/main/LICENSE)
|
|
9
|
+
|
|
10
|
+
**`@shulya/liquid-glass`** is an ultra-lightweight, zero-WebGL optical glass rendering engine for modern web applications. Turn any HTML container, card, navigation bar, modal, or interactive widget into a realistic refractive **Liquid Glass** block with real-time control over **`rim`**, **`ior`**, **`height`**, **`frosted`**, and **`fusion`** parameters.
|
|
11
|
+
|
|
12
|
+
- **Live Interactive Demo:** [https://liquid.shulya.tech](https://liquid.shulya.tech)
|
|
13
|
+
- **NPM Package:** [https://www.npmjs.com/package/@shulya/liquid-glass](https://www.npmjs.com/package/@shulya/liquid-glass)
|
|
14
|
+
- **GitHub Repository:** [https://github.com/shulya-tech/liquid-glass](https://github.com/shulya-tech/liquid-glass)
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why `@shulya/liquid-glass`?
|
|
21
|
+
|
|
22
|
+
- **Zero WebGL / Zero GPU Shader Overhead:** Does not spawn WebGL contexts or heavy fragment shaders. Runs on 100% standard browser primitives backed by pre-calibrated empirical lookup tables (`Float32Array` LUTs).
|
|
23
|
+
- **Mobile-First & Cool-Running:** Designed for 120 FPS responsiveness on smartphones and tablets with **0% CPU/GPU load when idle**—no battery drain or thermal throttling.
|
|
24
|
+
- **Toggleable Liquid Coalescence (`fusion`):** Enabled by default (`fusion: true`) for organic surface merging when elements approach one another, and can be disabled (`fusion: false`) on standalone blocks to skip proximity tracking for maximum performance.
|
|
25
|
+
- **Universal Framework Support:** First-class bindings included out of the box for **React**, **Vue 3**, **Svelte**, **Angular**, **SolidJS**, and **Vanilla JS**.
|
|
26
|
+
- **Pre-Calibrated Optical Matrix:** Uses a 256-point empirical optical calibration table (`tables/optical_calibration_matrix.xlsx`) for instant $O(1)$ linear lookup of edge deflection, specular rim luminance, and chromatic shift.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @shulya/liquid-glass
|
|
34
|
+
# or
|
|
35
|
+
pnpm add @shulya/liquid-glass
|
|
36
|
+
# or
|
|
37
|
+
yarn add @shulya/liquid-glass
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Interactive React Playground (`example/`)
|
|
43
|
+
|
|
44
|
+
> **Try it online right now:** [**https://liquid.shulya.tech**](https://liquid.shulya.tech)
|
|
45
|
+
> **Source code on GitHub:** [**github.com/shulya-tech/liquid-glass/tree/main/example**](https://github.com/shulya-tech/liquid-glass/tree/main/example)
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
The repository includes a complete **React + Vite** interactive playground in [`example/`](./example/) ([`example/src/App.jsx`](./example/src/App.jsx)) where you can drag three `<LiquidGlass>` components (a `136×74` capsule slider, a `196×116` rounded card, and a `112×112` circular lens) across a high-contrast optical test stage with a green pill track, diagonal rainbow ribbon, sunset sphere, black/white stripe grating, and centered `"Shulya"` typography.
|
|
50
|
+
|
|
51
|
+
All rendering in `example/` is powered directly by the `@shulya/liquid-glass/react` adapter (`<LiquidGlass>`, `scheduleStageRedraw`, `OPTICAL_DEFAULTS`) and the precomputed empirical lookup tables `_T0`–`_T4`.
|
|
52
|
+
|
|
53
|
+
### Running the React Playground Locally
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 1. Build the library bundles from the root directory
|
|
57
|
+
npm run build
|
|
58
|
+
|
|
59
|
+
# 2. Install example dependencies and start the Vite dev server
|
|
60
|
+
cd example
|
|
61
|
+
npm install
|
|
62
|
+
npm run dev
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or run `npm run example` directly from the repository root, then open **`http://localhost:5173`** in your browser to test:
|
|
66
|
+
|
|
67
|
+
- Dragging any of the 3 `<LiquidGlass>` React components over the typography, stripes, and color gradients.
|
|
68
|
+
- Bringing two or all three shapes close together to observe real-time liquid bridge coalescence (`fusion`).
|
|
69
|
+
- Adjusting **`Bevel Width (Rim)`** (`6–32 px`), **`Refraction (IOR)`** (`1.10–1.70`), **`Thickness (Height)`** (`6–34 px`), **`Frosted Blur`** (`0–30 px`), and toggling **`Liquid Fusion`** on/off in real time via the bottom control shelf.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Optical Parameters & Strict Bounds
|
|
74
|
+
|
|
75
|
+
Every component, hook, directive, and controller accepts the following properties. Out-of-range numeric inputs are automatically clamped to their physical `[min, max]` boundaries via `normalizeOptions()`:
|
|
76
|
+
|
|
77
|
+
| Parameter | Type | Default | Min | Max | Description |
|
|
78
|
+
| :----------------- | :--------------: | :--------: | :----: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| **`rim`** | `number` | **`16`** | `4` | `48` | Width of the curved perimeter bevel and specular edge highlight (in `px`). |
|
|
80
|
+
| **`ior`** | `number` | **`1.46`** | `1.05` | `2.20` | Optical Index of Refraction controlling background bending intensity. |
|
|
81
|
+
| **`height`** | `number` | **`18`** | `2` | `50` | Apparent elevation and optical thickness of the glass slab (in `px`). |
|
|
82
|
+
| **`frosted`** | `number` | **`0`** | `0` | `32` | Gaussian surface diffusion radius in `px` (`0` = crystal clear, `>0` = frosted satin glass). |
|
|
83
|
+
| **`fusion`** | `boolean` | **`true`** | — | — | Enables liquid surface coalescence with neighboring glass blocks. Set to **`false`** for isolated static blocks to bypass proximity checks and maximize speed. |
|
|
84
|
+
| **`borderRadius`** | `number \| null` | `null` | `0` | `999` | Optional override for corner radius in `px` (automatically inherits CSS `border-radius` when omitted). |
|
|
85
|
+
|
|
86
|
+
You can also import the frozen constants `OPTICAL_DEFAULTS` and `OPTICAL_LIMITS` from any entry point to bind UI sliders directly to the valid bounds.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Framework Integrations
|
|
91
|
+
|
|
92
|
+
### 1. React (`@shulya/liquid-glass/react`)
|
|
93
|
+
|
|
94
|
+
Use either the `<LiquidGlass>` component or the `useLiquidGlass` hook on any existing element:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { LiquidGlass, useLiquidGlass } from "@shulya/liquid-glass/react";
|
|
98
|
+
|
|
99
|
+
export function GlassCard() {
|
|
100
|
+
return (
|
|
101
|
+
<LiquidGlass
|
|
102
|
+
rim={16}
|
|
103
|
+
ior={1.46}
|
|
104
|
+
height={18}
|
|
105
|
+
frosted={0}
|
|
106
|
+
fusion={true}
|
|
107
|
+
className="p-6 rounded-3xl"
|
|
108
|
+
>
|
|
109
|
+
<h2>Liquid Glass Card</h2>
|
|
110
|
+
<p>Refractive optical container with zero WebGL overhead.</p>
|
|
111
|
+
</LiquidGlass>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Or via Hook (e.g. with fusion disabled for a static navbar):
|
|
116
|
+
export function StaticNavbar() {
|
|
117
|
+
const glassRef = useLiquidGlass<HTMLElement>({
|
|
118
|
+
rim: 16,
|
|
119
|
+
ior: 1.46,
|
|
120
|
+
height: 18,
|
|
121
|
+
frosted: 8,
|
|
122
|
+
fusion: false,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<nav ref={glassRef} className="top-nav">
|
|
127
|
+
Navigation
|
|
128
|
+
</nav>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### 2. Vue 3 (`@shulya/liquid-glass/vue`)
|
|
136
|
+
|
|
137
|
+
Use the `<LiquidGlass>` component or the `v-liquid-glass` directive:
|
|
138
|
+
|
|
139
|
+
```vue
|
|
140
|
+
<script setup>
|
|
141
|
+
import { ref } from "vue";
|
|
142
|
+
import { LiquidGlass, vLiquidGlass } from "@shulya/liquid-glass/vue";
|
|
143
|
+
|
|
144
|
+
const ior = ref(1.46);
|
|
145
|
+
const frosted = ref(0);
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<template>
|
|
149
|
+
<!-- Interactive coalescing glass block (fusion enabled by default) -->
|
|
150
|
+
<LiquidGlass
|
|
151
|
+
:rim="16"
|
|
152
|
+
:ior="ior"
|
|
153
|
+
:height="18"
|
|
154
|
+
:frosted="frosted"
|
|
155
|
+
:fusion="true"
|
|
156
|
+
class="glass-box"
|
|
157
|
+
>
|
|
158
|
+
<h3>Vue Liquid Glass</h3>
|
|
159
|
+
</LiquidGlass>
|
|
160
|
+
|
|
161
|
+
<!-- Standalone static glass block with fusion disabled for extra optimization -->
|
|
162
|
+
<section
|
|
163
|
+
v-liquid-glass="{
|
|
164
|
+
rim: 16,
|
|
165
|
+
ior: 1.46,
|
|
166
|
+
height: 18,
|
|
167
|
+
frosted: 0,
|
|
168
|
+
fusion: false,
|
|
169
|
+
}"
|
|
170
|
+
>
|
|
171
|
+
Optimized isolated glass block
|
|
172
|
+
</section>
|
|
173
|
+
</template>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### 3. Svelte (`@shulya/liquid-glass/svelte`)
|
|
179
|
+
|
|
180
|
+
Use the `use:liquidGlass` action on any HTML element. Reactive updates are handled automatically:
|
|
181
|
+
|
|
182
|
+
```svelte
|
|
183
|
+
<script>
|
|
184
|
+
import { liquidGlass } from '@shulya/liquid-glass/svelte';
|
|
185
|
+
|
|
186
|
+
let rim = 16;
|
|
187
|
+
let ior = 1.46;
|
|
188
|
+
let height = 18;
|
|
189
|
+
let frosted = 0;
|
|
190
|
+
let fusion = true;
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
<div
|
|
194
|
+
class="glass-panel"
|
|
195
|
+
use:liquidGlass={{ rim, ior, height, frosted, fusion }}
|
|
196
|
+
>
|
|
197
|
+
<h3>Svelte Liquid Glass</h3>
|
|
198
|
+
</div>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### 4. Angular (`@shulya/liquid-glass/angular`)
|
|
204
|
+
|
|
205
|
+
Attach `attachAngularLiquidGlass` inside your component or wire `LiquidGlassDirective`:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import {
|
|
209
|
+
Component,
|
|
210
|
+
ElementRef,
|
|
211
|
+
ViewChild,
|
|
212
|
+
AfterViewInit,
|
|
213
|
+
OnDestroy,
|
|
214
|
+
} from "@angular/core";
|
|
215
|
+
import {
|
|
216
|
+
attachAngularLiquidGlass,
|
|
217
|
+
LiquidGlassController,
|
|
218
|
+
} from "@shulya/liquid-glass/angular";
|
|
219
|
+
|
|
220
|
+
@Component({
|
|
221
|
+
selector: "app-glass-card",
|
|
222
|
+
standalone: true,
|
|
223
|
+
template: `
|
|
224
|
+
<div #glassBox class="glass-card">
|
|
225
|
+
<h3>Angular Liquid Glass</h3>
|
|
226
|
+
</div>
|
|
227
|
+
`,
|
|
228
|
+
})
|
|
229
|
+
export class GlassCardComponent implements AfterViewInit, OnDestroy {
|
|
230
|
+
@ViewChild("glassBox", { static: true }) glassBox!: ElementRef<HTMLElement>;
|
|
231
|
+
private controller?: LiquidGlassController;
|
|
232
|
+
|
|
233
|
+
ngAfterViewInit() {
|
|
234
|
+
this.controller = attachAngularLiquidGlass(this.glassBox, {
|
|
235
|
+
rim: 16,
|
|
236
|
+
ior: 1.46,
|
|
237
|
+
height: 18,
|
|
238
|
+
frosted: 0,
|
|
239
|
+
fusion: true,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
disableFusionForStaticMode() {
|
|
244
|
+
this.controller?.update({ fusion: false });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
ngOnDestroy() {
|
|
248
|
+
this.controller?.destroy();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### 5. SolidJS (`@shulya/liquid-glass/solid`)
|
|
256
|
+
|
|
257
|
+
Use the reactive `use:liquidGlass` directive with signals:
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
import { createSignal } from "solid-js";
|
|
261
|
+
import { liquidGlass } from "@shulya/liquid-glass/solid";
|
|
262
|
+
|
|
263
|
+
export function SolidGlassDemo() {
|
|
264
|
+
const [rim, setRim] = createSignal(16);
|
|
265
|
+
const [ior, setIor] = createSignal(1.46);
|
|
266
|
+
const [height, setHeight] = createSignal(18);
|
|
267
|
+
const [frosted, setFrosted] = createSignal(0);
|
|
268
|
+
const [fusion, setFusion] = createSignal(true);
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<div
|
|
272
|
+
class="glass-card"
|
|
273
|
+
use:liquidGlass={() => ({
|
|
274
|
+
rim: rim(),
|
|
275
|
+
ior: ior(),
|
|
276
|
+
height: height(),
|
|
277
|
+
frosted: frosted(),
|
|
278
|
+
fusion: fusion(),
|
|
279
|
+
})}
|
|
280
|
+
>
|
|
281
|
+
<h3>SolidJS Liquid Glass</h3>
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### 6. Vanilla JS / TypeScript (`@shulya/liquid-glass`)
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
import {
|
|
293
|
+
createLiquidGlass,
|
|
294
|
+
OPTICAL_DEFAULTS,
|
|
295
|
+
OPTICAL_LIMITS,
|
|
296
|
+
} from "@shulya/liquid-glass";
|
|
297
|
+
|
|
298
|
+
const glass = createLiquidGlass("#my-card", {
|
|
299
|
+
rim: 16, // Clamped between [4, 48]
|
|
300
|
+
ior: 1.46, // Clamped between [1.05, 2.20]
|
|
301
|
+
height: 18, // Clamped between [2, 50]
|
|
302
|
+
frosted: 0, // Clamped between [0, 32]
|
|
303
|
+
fusion: true, // Default: true (set false to isolate element)
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Dynamically update parameters at any time:
|
|
307
|
+
glass.update({
|
|
308
|
+
rim: 24,
|
|
309
|
+
ior: 1.62,
|
|
310
|
+
height: 28,
|
|
311
|
+
frosted: 8,
|
|
312
|
+
fusion: false,
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Pre-Computed Calibration Dataset
|
|
319
|
+
|
|
320
|
+
To guarantee zero runtime trigonometric or shader overhead across mobile devices, `@shulya/liquid-glass` ships with pre-sampled empirical lookup arrays located in:
|
|
321
|
+
|
|
322
|
+
- `tables/optical_calibration_matrix.xlsx` (Excel workbook for inspection and studio tuning)
|
|
323
|
+
- `tables/optical_calibration_matrix.csv` (CSV mirror)
|
|
324
|
+
- `dist/tables.mjs` (`Float32Array` runtime buffers `_T0` – `_T4`)
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Links
|
|
329
|
+
|
|
330
|
+
- **Live Demo:** [https://liquid.shulya.tech](https://liquid.shulya.tech)
|
|
331
|
+
- **NPM Package:** [https://www.npmjs.com/package/@shulya/liquid-glass](https://www.npmjs.com/package/@shulya/liquid-glass)
|
|
332
|
+
- **GitHub Repository:** [https://github.com/shulya-tech/liquid-glass](https://github.com/shulya-tech/liquid-glass)
|
|
333
|
+
- **Issue Tracker:** [https://github.com/shulya-tech/liquid-glass/issues](https://github.com/shulya-tech/liquid-glass/issues)
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## License
|
|
338
|
+
|
|
339
|
+
MIT © [Shulya LLC](https://github.com/shulya-tech)
|
package/dist/angular.cjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Angular Adapter for Liquid Glass UI
|
|
3
|
+
*/
|
|
4
|
+
const { LiquidGlassController, OPTICAL_DEFAULTS, OPTICAL_LIMITS } = require('./core.cjs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Framework-agnostic Angular Directive Controller Class
|
|
8
|
+
* Can be used directly with Angular's @Directive({ selector: '[liquidGlass]', standalone: true })
|
|
9
|
+
* or instantiated via ElementRef in any Angular component.
|
|
10
|
+
*/
|
|
11
|
+
const LiquidGlassDirective = exports.LiquidGlassDirective = class LiquidGlassDirective {
|
|
12
|
+
/**
|
|
13
|
+
* @param {{ nativeElement: HTMLElement } | HTMLElement} elementRef
|
|
14
|
+
*/
|
|
15
|
+
constructor(elementRef) {
|
|
16
|
+
this.el = elementRef && elementRef.nativeElement ? elementRef.nativeElement : elementRef;
|
|
17
|
+
this.rim = OPTICAL_DEFAULTS.rim;
|
|
18
|
+
this.ior = OPTICAL_DEFAULTS.ior;
|
|
19
|
+
this.height = OPTICAL_DEFAULTS.height;
|
|
20
|
+
this.frosted = OPTICAL_DEFAULTS.frosted;
|
|
21
|
+
this.fusion = OPTICAL_DEFAULTS.fusion;
|
|
22
|
+
this.borderRadius = null;
|
|
23
|
+
this.liquidGlass = null;
|
|
24
|
+
this._controller = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
ngOnInit() {
|
|
28
|
+
const opts =
|
|
29
|
+
typeof this.liquidGlass === 'object' && this.liquidGlass !== null
|
|
30
|
+
? this.liquidGlass
|
|
31
|
+
: {
|
|
32
|
+
rim: this.rim,
|
|
33
|
+
ior: this.ior,
|
|
34
|
+
height: this.height,
|
|
35
|
+
frosted: this.frosted,
|
|
36
|
+
fusion: this.fusion,
|
|
37
|
+
borderRadius: this.borderRadius
|
|
38
|
+
};
|
|
39
|
+
this._controller = new LiquidGlassController(this.el, opts);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
ngOnChanges() {
|
|
43
|
+
if (this._controller) {
|
|
44
|
+
const opts =
|
|
45
|
+
typeof this.liquidGlass === 'object' && this.liquidGlass !== null
|
|
46
|
+
? this.liquidGlass
|
|
47
|
+
: {
|
|
48
|
+
rim: this.rim,
|
|
49
|
+
ior: this.ior,
|
|
50
|
+
height: this.height,
|
|
51
|
+
frosted: this.frosted,
|
|
52
|
+
fusion: this.fusion,
|
|
53
|
+
borderRadius: this.borderRadius
|
|
54
|
+
};
|
|
55
|
+
this._controller.update(opts);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ngOnDestroy() {
|
|
60
|
+
if (this._controller) {
|
|
61
|
+
this._controller.destroy();
|
|
62
|
+
this._controller = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Helper to attach LiquidGlass directly inside Angular ngAfterViewInit
|
|
69
|
+
*/
|
|
70
|
+
exports.attachAngularLiquidGlass = function attachAngularLiquidGlass(elementRef, options = {}) {
|
|
71
|
+
const el = elementRef && elementRef.nativeElement ? elementRef.nativeElement : elementRef;
|
|
72
|
+
return new LiquidGlassController(el, options);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
exports.LiquidGlassController = LiquidGlassController;
|
|
76
|
+
exports.OPTICAL_DEFAULTS = OPTICAL_DEFAULTS;
|
|
77
|
+
exports.OPTICAL_LIMITS = OPTICAL_LIMITS;
|
|
78
|
+
exports.default = LiquidGlassDirective;
|
package/dist/angular.mjs
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Angular Adapter for Liquid Glass UI
|
|
3
|
+
*/
|
|
4
|
+
import { LiquidGlassController, OPTICAL_DEFAULTS, OPTICAL_LIMITS } from './core.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Framework-agnostic Angular Directive Controller Class
|
|
8
|
+
* Can be used directly with Angular's @Directive({ selector: '[liquidGlass]', standalone: true })
|
|
9
|
+
* or instantiated via ElementRef in any Angular component.
|
|
10
|
+
*/
|
|
11
|
+
export class LiquidGlassDirective {
|
|
12
|
+
/**
|
|
13
|
+
* @param {{ nativeElement: HTMLElement } | HTMLElement} elementRef
|
|
14
|
+
*/
|
|
15
|
+
constructor(elementRef) {
|
|
16
|
+
this.el = elementRef && elementRef.nativeElement ? elementRef.nativeElement : elementRef;
|
|
17
|
+
this.rim = OPTICAL_DEFAULTS.rim;
|
|
18
|
+
this.ior = OPTICAL_DEFAULTS.ior;
|
|
19
|
+
this.height = OPTICAL_DEFAULTS.height;
|
|
20
|
+
this.frosted = OPTICAL_DEFAULTS.frosted;
|
|
21
|
+
this.fusion = OPTICAL_DEFAULTS.fusion;
|
|
22
|
+
this.borderRadius = null;
|
|
23
|
+
this.liquidGlass = null;
|
|
24
|
+
this._controller = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
ngOnInit() {
|
|
28
|
+
const opts =
|
|
29
|
+
typeof this.liquidGlass === 'object' && this.liquidGlass !== null
|
|
30
|
+
? this.liquidGlass
|
|
31
|
+
: {
|
|
32
|
+
rim: this.rim,
|
|
33
|
+
ior: this.ior,
|
|
34
|
+
height: this.height,
|
|
35
|
+
frosted: this.frosted,
|
|
36
|
+
fusion: this.fusion,
|
|
37
|
+
borderRadius: this.borderRadius
|
|
38
|
+
};
|
|
39
|
+
this._controller = new LiquidGlassController(this.el, opts);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
ngOnChanges() {
|
|
43
|
+
if (this._controller) {
|
|
44
|
+
const opts =
|
|
45
|
+
typeof this.liquidGlass === 'object' && this.liquidGlass !== null
|
|
46
|
+
? this.liquidGlass
|
|
47
|
+
: {
|
|
48
|
+
rim: this.rim,
|
|
49
|
+
ior: this.ior,
|
|
50
|
+
height: this.height,
|
|
51
|
+
frosted: this.frosted,
|
|
52
|
+
fusion: this.fusion,
|
|
53
|
+
borderRadius: this.borderRadius
|
|
54
|
+
};
|
|
55
|
+
this._controller.update(opts);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ngOnDestroy() {
|
|
60
|
+
if (this._controller) {
|
|
61
|
+
this._controller.destroy();
|
|
62
|
+
this._controller = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Helper to attach LiquidGlass directly inside Angular ngAfterViewInit
|
|
69
|
+
*/
|
|
70
|
+
export function attachAngularLiquidGlass(elementRef, options = {}) {
|
|
71
|
+
const el = elementRef && elementRef.nativeElement ? elementRef.nativeElement : elementRef;
|
|
72
|
+
return new LiquidGlassController(el, options);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { LiquidGlassController, OPTICAL_DEFAULTS, OPTICAL_LIMITS };
|
|
76
|
+
export default LiquidGlassDirective;
|