@vanduo-oss/framework 1.4.5 → 1.5.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +23 -9
  3. package/css/primitives/primitives.css +257 -0
  4. package/css/utilities/print.css +19 -17
  5. package/css/vanduo.css +9 -3
  6. package/dist/build-info.json +3 -3
  7. package/dist/vanduo-core.css +19701 -0
  8. package/dist/vanduo-core.css.map +1 -0
  9. package/dist/vanduo-core.min.css +2 -0
  10. package/dist/vanduo-core.min.css.map +1 -0
  11. package/dist/vanduo.cjs.js +39 -19
  12. package/dist/vanduo.cjs.js.map +2 -2
  13. package/dist/vanduo.cjs.min.js +5 -5
  14. package/dist/vanduo.cjs.min.js.map +3 -3
  15. package/dist/vanduo.css +628 -33585
  16. package/dist/vanduo.css.map +1 -1
  17. package/dist/vanduo.d.ts +77 -0
  18. package/dist/vanduo.esm.js +39 -19
  19. package/dist/vanduo.esm.js.map +2 -2
  20. package/dist/vanduo.esm.min.js +5 -5
  21. package/dist/vanduo.esm.min.js.map +3 -3
  22. package/dist/vanduo.js +39 -19
  23. package/dist/vanduo.js.map +2 -2
  24. package/dist/vanduo.min.css +2 -2
  25. package/dist/vanduo.min.css.map +1 -1
  26. package/dist/vanduo.min.js +5 -5
  27. package/dist/vanduo.min.js.map +3 -3
  28. package/js/components/parallax.js +13 -7
  29. package/js/components/spotlight.js +46 -16
  30. package/package.json +7 -3
  31. package/css/components/doc-tabs.css +0 -38
  32. package/dist/icons/phosphor/bold/Phosphor-Bold.svg +0 -3057
  33. package/dist/icons/phosphor/bold/Phosphor-Bold.ttf +0 -0
  34. package/dist/icons/phosphor/bold/Phosphor-Bold.woff +0 -0
  35. package/dist/icons/phosphor/bold/Phosphor-Bold.woff2 +0 -0
  36. package/dist/icons/phosphor/bold/style.css +0 -4627
  37. package/dist/icons/phosphor/duotone/Phosphor-Duotone.svg +0 -3054
  38. package/dist/icons/phosphor/duotone/Phosphor-Duotone.ttf +0 -0
  39. package/dist/icons/phosphor/duotone/Phosphor-Duotone.woff +0 -0
  40. package/dist/icons/phosphor/duotone/Phosphor-Duotone.woff2 +0 -0
  41. package/dist/icons/phosphor/duotone/style.css +0 -12115
  42. package/dist/icons/phosphor/light/Phosphor-Light.svg +0 -3057
  43. package/dist/icons/phosphor/light/Phosphor-Light.ttf +0 -0
  44. package/dist/icons/phosphor/light/Phosphor-Light.woff +0 -0
  45. package/dist/icons/phosphor/light/Phosphor-Light.woff2 +0 -0
  46. package/dist/icons/phosphor/light/style.css +0 -4627
  47. package/dist/icons/phosphor/thin/Phosphor-Thin.svg +0 -3057
  48. package/dist/icons/phosphor/thin/Phosphor-Thin.ttf +0 -0
  49. package/dist/icons/phosphor/thin/Phosphor-Thin.woff +0 -0
  50. package/dist/icons/phosphor/thin/Phosphor-Thin.woff2 +0 -0
  51. package/dist/icons/phosphor/thin/style.css +0 -4627
  52. package/js/components/vd-hex.js +0 -838
  53. package/js/utils/hex-math.js +0 -233
@@ -64,15 +64,17 @@
64
64
  initParallax: function (element) {
65
65
  element.dataset.parallaxInitialized = 'true';
66
66
 
67
- // Check if disabled on mobile
68
- const disableMobile = element.classList.contains('parallax-disable-mobile');
67
+ // Check if disabled on mobile (vd- prefixed; unprefixed kept for back-compat)
68
+ const disableMobile = element.classList.contains('vd-parallax-disable-mobile')
69
+ || element.classList.contains('parallax-disable-mobile');
69
70
  if (disableMobile && this.isMobile) {
70
71
  return;
71
72
  }
72
73
 
73
74
  const layers = element.querySelectorAll('.vd-parallax-layer, .vd-parallax-bg');
74
75
  const speed = this.getSpeed(element);
75
- const direction = element.classList.contains('parallax-horizontal') ? 'horizontal' : 'vertical';
76
+ const direction = (element.classList.contains('vd-parallax-horizontal')
77
+ || element.classList.contains('parallax-horizontal')) ? 'horizontal' : 'vertical';
76
78
 
77
79
  this.parallaxElements.set(element, {
78
80
  layers: Array.from(layers),
@@ -91,9 +93,11 @@
91
93
  * @returns {number} Speed multiplier
92
94
  */
93
95
  getSpeed: function (element) {
94
- if (element.classList.contains('parallax-slow')) {
96
+ if (element.classList.contains('vd-parallax-slow')
97
+ || element.classList.contains('parallax-slow')) {
95
98
  return 0.5;
96
- } else if (element.classList.contains('parallax-fast')) {
99
+ } else if (element.classList.contains('vd-parallax-fast')
100
+ || element.classList.contains('parallax-fast')) {
97
101
  return 1.5;
98
102
  }
99
103
  return 1; // Default medium speed
@@ -150,8 +154,10 @@
150
154
  const offset = (scrollProgress - 0.5) * config.speed * 100;
151
155
 
152
156
  config.layers.forEach((layer, _index) => {
153
- // Different layers can have different speeds
154
- const layerSpeed = layer.dataset.parallaxSpeed ? parseFloat(layer.dataset.parallaxSpeed) : 1;
157
+ // Different layers can have different speeds. Accept data-parallax-speed
158
+ // (canonical) or data-speed (back-compat).
159
+ const layerSpeedAttr = layer.dataset.parallaxSpeed || layer.dataset.speed;
160
+ const layerSpeed = layerSpeedAttr ? parseFloat(layerSpeedAttr) : 1;
155
161
  const layerOffset = offset * layerSpeed;
156
162
 
157
163
  if (config.direction === 'horizontal') {
@@ -14,6 +14,7 @@
14
14
  _cleanup: [],
15
15
  _boundTriggers: new WeakMap(),
16
16
  _triggerElement: null,
17
+ _currentTarget: null,
17
18
 
18
19
  init: function (root) {
19
20
  const triggers = window.Vanduo.queryAll(root, '[data-vd-spotlight]');
@@ -113,9 +114,39 @@
113
114
  // Overlay click to close
114
115
  overlay.addEventListener('click', () => this.stop());
115
116
 
117
+ // Keep the tooltip glued to its target while active — through the smooth
118
+ // scrollIntoView and any late layout (e.g. content-visibility sections that
119
+ // only render their real geometry once scrolled into view).
120
+ const reposition = () => {
121
+ if (this._active && this._currentTarget) this._positionTooltip(this._currentTarget);
122
+ };
123
+ window.addEventListener('scroll', reposition, { passive: true });
124
+ window.addEventListener('resize', reposition);
125
+ this._cleanup.push(() => window.removeEventListener('scroll', reposition));
126
+ this._cleanup.push(() => window.removeEventListener('resize', reposition));
127
+
116
128
  this._showStep(this._currentStep);
117
129
  },
118
130
 
131
+ _positionTooltip: function (target) {
132
+ const tooltip = this._elements.tooltip;
133
+ if (!tooltip || !target || !target.isConnected) return;
134
+
135
+ const rect = target.getBoundingClientRect();
136
+ const tRect = tooltip.getBoundingClientRect();
137
+ let top = rect.bottom + 12 + window.scrollY;
138
+ let left = rect.left + (rect.width - tRect.width) / 2 + window.scrollX;
139
+
140
+ // Keep in viewport
141
+ left = Math.max(8, Math.min(left, window.innerWidth - tRect.width - 8));
142
+ if (top + tRect.height > window.innerHeight + window.scrollY) {
143
+ top = rect.top - tRect.height - 12 + window.scrollY;
144
+ }
145
+
146
+ tooltip.style.top = top + 'px';
147
+ tooltip.style.left = left + 'px';
148
+ },
149
+
119
150
  _showStep: function (index) {
120
151
  const step = this._steps[index];
121
152
  if (!step) return;
@@ -206,23 +237,21 @@
206
237
  footer.appendChild(actions);
207
238
  tooltip.appendChild(footer);
208
239
 
209
- // Position tooltip near target
240
+ // Position the tooltip near the target. A single measurement right after a
241
+ // smooth scrollIntoView is unreliable: the scroll is still animating and the
242
+ // target's final geometry may not exist yet (content-visibility sections only
243
+ // render once scrolled into view). Re-position across the settle window so the
244
+ // tooltip converges on the correct spot; the scroll/resize listeners keep it
245
+ // there afterward.
246
+ this._currentTarget = target || null;
210
247
  if (target) {
211
- requestAnimationFrame(() => {
212
- const rect = target.getBoundingClientRect();
213
- const tRect = tooltip.getBoundingClientRect();
214
- let top = rect.bottom + 12 + window.scrollY;
215
- let left = rect.left + (rect.width - tRect.width) / 2 + window.scrollX;
216
-
217
- // Keep in viewport
218
- left = Math.max(8, Math.min(left, window.innerWidth - tRect.width - 8));
219
- if (top + tRect.height > window.innerHeight + window.scrollY) {
220
- top = rect.top - tRect.height - 12 + window.scrollY;
221
- }
222
-
223
- tooltip.style.top = top + 'px';
224
- tooltip.style.left = left + 'px';
225
- });
248
+ let frames = 0;
249
+ const settle = () => {
250
+ if (!this._active || this._currentTarget !== target) return;
251
+ this._positionTooltip(target);
252
+ if (frames++ < 30) requestAnimationFrame(settle);
253
+ };
254
+ requestAnimationFrame(settle);
226
255
  }
227
256
 
228
257
  document.dispatchEvent(new CustomEvent('spotlight:step', {
@@ -272,6 +301,7 @@
272
301
  this._elements = {};
273
302
  this._steps = [];
274
303
  this._currentStep = 0;
304
+ this._currentTarget = null;
275
305
 
276
306
  if (this._triggerElement && this._triggerElement.isConnected && typeof this._triggerElement.focus === 'function') {
277
307
  this._triggerElement.focus();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanduo-oss/framework",
3
- "version": "1.4.5",
3
+ "version": "1.5.0",
4
4
  "description": "Zero-dependency CSS/JS framework built on Fibonacci/Golden Ratio design system with Open Color integration",
5
5
  "keywords": [
6
6
  "css",
@@ -21,13 +21,16 @@
21
21
  "type": "module",
22
22
  "main": "dist/vanduo.cjs.js",
23
23
  "module": "dist/vanduo.esm.js",
24
+ "types": "./dist/vanduo.d.ts",
24
25
  "exports": {
25
26
  ".": {
27
+ "types": "./dist/vanduo.d.ts",
26
28
  "import": "./dist/vanduo.esm.js",
27
29
  "require": "./dist/vanduo.cjs.js",
28
30
  "default": "./dist/vanduo.esm.js"
29
31
  },
30
32
  "./css": "./dist/vanduo.min.css",
33
+ "./css/core": "./dist/vanduo-core.min.css",
31
34
  "./iife": "./dist/vanduo.min.js",
32
35
  "./package.json": "./package.json"
33
36
  },
@@ -36,12 +39,13 @@
36
39
  "css/",
37
40
  "js/",
38
41
  "fonts/",
39
- "icons/"
42
+ "icons/",
43
+ "CHANGELOG.md"
40
44
  ],
41
45
  "devDependencies": {
42
46
  "@eslint/js": "^10.0.1",
43
47
  "@playwright/test": "^1.60.0",
44
- "esbuild": "^0.28.0",
48
+ "esbuild": "^0.28.1",
45
49
  "eslint": "^10.4.1",
46
50
  "husky": "^9.1.7",
47
51
  "lightningcss": "^1.32.0",
@@ -1,38 +0,0 @@
1
- /**
2
- * Vanduo Documentation Tabs Component
3
- * Provides styled tab navigation for documentation sections
4
- */
5
-
6
- .doc-tabs {
7
- display: flex;
8
- gap: 0.5rem;
9
- margin: 1rem 0 1.5rem;
10
- flex-wrap: wrap;
11
- }
12
-
13
- .doc-tab {
14
- display: inline-flex;
15
- align-items: center;
16
- gap: 0.4rem;
17
- padding: 0.6rem 1rem;
18
- border: 1px solid var(--vd-border-color);
19
- border-radius: var(--vd-btn-border-radius);
20
- background: var(--vd-bg-secondary);
21
- color: var(--vd-text-primary);
22
- text-decoration: none;
23
- font-weight: 500;
24
- transition: all 0.2s ease;
25
- }
26
-
27
- .doc-tab:hover {
28
- border-color: var(--vd-color-primary);
29
- color: var(--vd-color-primary);
30
- background: var(--vd-color-primary-alpha-08);
31
- }
32
-
33
- .doc-tab.active {
34
- border-color: var(--vd-color-primary);
35
- color: var(--vd-text-on-primary);
36
- background: var(--vd-color-primary);
37
- box-shadow: 0 0 0 1px var(--vd-color-primary-alpha-20);
38
- }