@vanduo-oss/framework 1.2.6 → 1.2.8

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 (54) hide show
  1. package/README.md +39 -5
  2. package/css/components/affix.css +53 -0
  3. package/css/components/bubble.css +165 -0
  4. package/css/components/datepicker.css +216 -0
  5. package/css/components/fab.css +225 -0
  6. package/css/components/flow.css +265 -0
  7. package/css/components/rating.css +112 -0
  8. package/css/components/ripple.css +63 -0
  9. package/css/components/sidenav.css +70 -0
  10. package/css/components/spotlight.css +119 -0
  11. package/css/components/stepper.css +176 -0
  12. package/css/components/suggest.css +119 -0
  13. package/css/components/timeline.css +201 -0
  14. package/css/components/timepicker.css +80 -0
  15. package/css/components/transfer.css +165 -0
  16. package/css/components/tree.css +173 -0
  17. package/css/components/waypoint.css +59 -0
  18. package/css/vanduo.css +17 -0
  19. package/dist/build-info.json +3 -3
  20. package/dist/vanduo.cjs.js +2161 -6
  21. package/dist/vanduo.cjs.js.map +4 -4
  22. package/dist/vanduo.cjs.min.js +5 -5
  23. package/dist/vanduo.cjs.min.js.map +4 -4
  24. package/dist/vanduo.css +1947 -5
  25. package/dist/vanduo.css.map +1 -1
  26. package/dist/vanduo.esm.js +2161 -6
  27. package/dist/vanduo.esm.js.map +4 -4
  28. package/dist/vanduo.esm.min.js +5 -5
  29. package/dist/vanduo.esm.min.js.map +4 -4
  30. package/dist/vanduo.js +2161 -6
  31. package/dist/vanduo.js.map +4 -4
  32. package/dist/vanduo.min.css +2 -2
  33. package/dist/vanduo.min.css.map +1 -1
  34. package/dist/vanduo.min.js +5 -5
  35. package/dist/vanduo.min.js.map +4 -4
  36. package/js/components/affix.js +129 -0
  37. package/js/components/bubble.js +203 -0
  38. package/js/components/datepicker.js +287 -0
  39. package/js/components/flow.js +264 -0
  40. package/js/components/rating.js +160 -0
  41. package/js/components/ripple.js +74 -0
  42. package/js/components/sidenav.js +9 -2
  43. package/js/components/spotlight.js +295 -0
  44. package/js/components/stepper.js +97 -0
  45. package/js/components/suggest.js +219 -0
  46. package/js/components/theme-customizer.js +11 -2
  47. package/js/components/theme-switcher.js +7 -0
  48. package/js/components/timepicker.js +142 -0
  49. package/js/components/transfer.js +206 -0
  50. package/js/components/tree.js +191 -0
  51. package/js/components/validate.js +185 -0
  52. package/js/components/waypoint.js +120 -0
  53. package/js/index.js +16 -0
  54. package/package.json +4 -4
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Vanduo Framework v1.2.6
1
+ # Vanduo Framework v1.2.8
2
2
 
3
3
  <p align="center">
4
4
  <img src="vanduo-banner.svg" alt="Vanduo Framework Banner" width="100%">
@@ -19,7 +19,7 @@
19
19
 
20
20
  ## Overview
21
21
 
22
- A lightweight, pure HTML/CSS/JS framework for designing beautiful interfaces. Zero runtime dependencies, no mandatory build tools, just clean and simple code.
22
+ A lightweight, pure HTML/CSS/JS framework with **45+ components** for designing beautiful interfaces. Zero runtime dependencies, no mandatory build tools, just clean and simple code.
23
23
 
24
24
  [**Browse Full Documentation →**](https://vanduo.dev/#docs)
25
25
 
@@ -32,11 +32,44 @@ A lightweight, pure HTML/CSS/JS framework for designing beautiful interfaces. Ze
32
32
  - 🧩 **Modular** - Import only what you need
33
33
  - ♿ **Accessible** - Built with accessibility in mind (WCAG 2.1 AA)
34
34
  - 🌙 **Dark Mode** - Automatic OS preference detection + manual toggle
35
+ - 🌗 **Theme Switcher** - Lightweight light/dark/system toggle with shared preference storage
35
36
  - 🎛️ **Theme Customizer** - Real-time color, radius, font, and mode customization
36
37
  - 🔍 **SEO-Ready** - Comprehensive meta tags, structured data, and sitemap
37
38
 
38
39
  ---
39
40
 
41
+ ## What's New in v1.2.8
42
+
43
+ v1.2.8 focuses on theme-system clarity and release-surface alignment:
44
+
45
+ - **Theme Switcher and Theme Customizer are now treated as distinct tooling components.** Use Theme Switcher for lightweight system/light/dark toggles and Theme Customizer for full palette, neutral, radius, font, and mode control.
46
+ - **Shared theme coordination is more predictable.** When both components are present, they keep the shared theme preference synchronized and only swap between default per-theme primary colors when the user is still on the default primary.
47
+ - **Release-facing docs were refreshed for v1.2.8.** The docs site now has dedicated Theme Switcher documentation, expanded Theme Customizer coordination guidance, and aligned versioned release copy.
48
+
49
+ The framework still ships **45+ components**, including the v1.2.7 additions below.
50
+
51
+ | Component | Vanduo Name | Type |
52
+ |---|---|---|
53
+ | Carousel | Flow | CSS + JS |
54
+ | Popover | Bubble | CSS + JS |
55
+ | Scrollspy | Waypoint | CSS + JS |
56
+ | Offcanvas | — (enhanced Sidenav) | CSS + JS |
57
+ | Ripple / Waves | Ripple | CSS + JS |
58
+ | Floating Action Button | FAB | CSS-only |
59
+ | Sticky | Affix | CSS + JS |
60
+ | Autocomplete | Suggest | CSS + JS |
61
+ | Form Validation | Validate | JS |
62
+ | Date Picker | Datepicker | CSS + JS |
63
+ | Time Picker | Timepicker | CSS + JS |
64
+ | Stepper | Stepper | CSS + JS |
65
+ | Timeline | Timeline | CSS-only |
66
+ | Rating | Rating | CSS + JS |
67
+ | Transfer / Multi-select | Transfer | CSS + JS |
68
+ | Tree View | Tree | CSS + JS |
69
+ | Spotlight / Feature Discovery | Spotlight | CSS + JS |
70
+
71
+ ---
72
+
40
73
  ## Quick Start
41
74
 
42
75
  ### Option 1: CDN (Recommended)
@@ -54,8 +87,8 @@ The quickest way to get started — no install, no build step. Add two lines to
54
87
 
55
88
  **Pin to a specific version** for production:
56
89
  ```html
57
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.2.5/dist/vanduo.min.css">
58
- <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.2.5/dist/vanduo.min.js"></script>
90
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.2.8/dist/vanduo.min.css">
91
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.2.8/dist/vanduo.min.js"></script>
59
92
  <script>Vanduo.init();</script>
60
93
  ```
61
94
 
@@ -118,7 +151,7 @@ This project includes an [`llms.txt`](llms.txt) file — a structured markdown s
118
151
  Use the hardened upload script to attach only approved bundle artifacts from `dist/`:
119
152
 
120
153
  ```bash
121
- pnpm run release:assets -- v1.2.5
154
+ pnpm run release:assets -- v1.2.8
122
155
  ```
123
156
 
124
157
  Notes:
@@ -136,6 +169,7 @@ Comprehensive documentation for all components, utilities, and customization opt
136
169
  ### Key Capabilities
137
170
 
138
171
  * **Dark Mode**: Works automatically with system preferences. Can be forced via `data-theme="dark"` on `<html>`.
172
+ * **Theme Switcher**: Lightweight light/dark/system toggle that can coexist with Theme Customizer.
139
173
  * **Theme Customizer**: Built-in runtime tool to change colors, fonts, and radius.
140
174
  * **Modular Imports**: Import only specific components (e.g., `css/components/buttons.css`) to keep your site lean.
141
175
  * **Icons**: Includes [Phosphor Icons](https://phosphoricons.com) (Regular + Fill weights bundled).
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Vanduo Framework - Affix (Sticky)
3
+ * Scroll-aware sticky positioning with is-stuck state
4
+ * Primary: .vd-affix | Alias: .vd-sticky
5
+ */
6
+
7
+ :root {
8
+ --affix-top-offset: 0;
9
+ --affix-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
10
+ --affix-transition: box-shadow 0.2s ease, background-color 0.2s ease;
11
+ --affix-z-index: 1020;
12
+ }
13
+
14
+ [data-theme="dark"] {
15
+ --affix-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
16
+ }
17
+
18
+ @media (prefers-color-scheme: dark) {
19
+ :root:not([data-theme]) {
20
+ --affix-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
21
+ }
22
+ }
23
+
24
+ /* ========== Base ========== */
25
+
26
+ .vd-affix,
27
+ .vd-sticky,
28
+ [data-vd-affix] {
29
+ position: sticky;
30
+ top: var(--affix-top-offset);
31
+ transition: var(--affix-transition);
32
+ z-index: calc(var(--affix-z-index) - 1);
33
+ }
34
+
35
+ /* ========== Stuck State ========== */
36
+
37
+ .vd-affix.is-stuck,
38
+ .vd-sticky.is-stuck,
39
+ [data-vd-affix].is-stuck {
40
+ z-index: var(--affix-z-index);
41
+ box-shadow: var(--affix-shadow);
42
+ }
43
+
44
+ /* ========== Variants ========== */
45
+
46
+ .vd-affix-no-shadow.is-stuck {
47
+ box-shadow: none;
48
+ }
49
+
50
+ .vd-affix-bordered.is-stuck {
51
+ box-shadow: none;
52
+ border-bottom: 1px solid var(--border-color, #dee2e6);
53
+ }
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Vanduo Framework - Bubble (Popover)
3
+ * Click-triggered rich content popover
4
+ * Primary: .vd-bubble | Alias: .vd-popover
5
+ */
6
+
7
+ :root {
8
+ /* Bubble Colors */
9
+ --bubble-bg: var(--card-bg, #fff);
10
+ --bubble-text: var(--text-primary, #212529);
11
+ --bubble-border-color: var(--border-color, #dee2e6);
12
+ --bubble-shadow: 0 0.5rem 1.3125rem rgba(0, 0, 0, 0.12); /* 8px 21px - fib */
13
+
14
+ /* Bubble Spacing (Fibonacci) */
15
+ --bubble-padding: 0.8125rem; /* 13px - fib */
16
+ --bubble-header-padding: 0.5rem 0.8125rem; /* 8px 13px */
17
+ --bubble-arrow-size: 8px; /* fib */
18
+
19
+ /* Bubble Sizing */
20
+ --bubble-max-width: 21rem; /* 336px - fib×16 */
21
+ --bubble-min-width: 8rem;
22
+ --bubble-border-radius: var(--border-radius, 0.5rem);
23
+
24
+ /* Bubble Z-index */
25
+ --bubble-z-index: 1060;
26
+
27
+ /* Bubble Font */
28
+ --bubble-font-size: var(--font-size-sm, 0.875rem);
29
+ }
30
+
31
+ /* Dark Theme */
32
+ [data-theme="dark"] {
33
+ --bubble-bg: var(--card-bg, #2d2d44);
34
+ --bubble-border-color: var(--border-color, #3d3d5c);
35
+ --bubble-shadow: 0 0.5rem 1.3125rem rgba(0, 0, 0, 0.3);
36
+ }
37
+
38
+ @media (prefers-color-scheme: dark) {
39
+ :root:not([data-theme]) {
40
+ --bubble-bg: var(--card-bg, #2d2d44);
41
+ --bubble-border-color: var(--border-color, #3d3d5c);
42
+ --bubble-shadow: 0 0.5rem 1.3125rem rgba(0, 0, 0, 0.3);
43
+ }
44
+ }
45
+
46
+ /* ========== Base ========== */
47
+
48
+ .vd-bubble-content,
49
+ .vd-popover-content {
50
+ position: absolute;
51
+ z-index: var(--bubble-z-index);
52
+ max-width: var(--bubble-max-width);
53
+ min-width: var(--bubble-min-width);
54
+ background: var(--bubble-bg);
55
+ color: var(--bubble-text);
56
+ border: 1px solid var(--bubble-border-color);
57
+ border-radius: var(--bubble-border-radius);
58
+ box-shadow: var(--bubble-shadow);
59
+ font-size: var(--bubble-font-size);
60
+ opacity: 0;
61
+ visibility: hidden;
62
+ transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
63
+ transform: scale(0.95);
64
+ pointer-events: none;
65
+ }
66
+
67
+ .vd-bubble-content.is-visible,
68
+ .vd-popover-content.is-visible {
69
+ opacity: 1;
70
+ visibility: visible;
71
+ transform: scale(1);
72
+ pointer-events: auto;
73
+ }
74
+
75
+ /* ========== Header ========== */
76
+
77
+ .vd-bubble-header {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: space-between;
81
+ padding: var(--bubble-header-padding);
82
+ border-bottom: 1px solid var(--bubble-border-color);
83
+ font-weight: 600;
84
+ }
85
+
86
+ /* ========== Body ========== */
87
+
88
+ .vd-bubble-body {
89
+ padding: var(--bubble-padding);
90
+ }
91
+
92
+ /* ========== Close Button ========== */
93
+
94
+ .vd-bubble-close {
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ width: 1.5rem;
99
+ height: 1.5rem;
100
+ padding: 0;
101
+ margin-left: 0.5rem;
102
+ border: none;
103
+ border-radius: 50%;
104
+ background: transparent;
105
+ color: var(--bubble-text);
106
+ font-size: 1.125rem;
107
+ line-height: 1;
108
+ cursor: pointer;
109
+ opacity: 0.5;
110
+ transition: opacity 0.15s ease;
111
+ }
112
+
113
+ .vd-bubble-close:hover { opacity: 1; }
114
+
115
+ /* ========== Arrow ========== */
116
+
117
+ .vd-bubble-content::before,
118
+ .vd-popover-content::before {
119
+ content: '';
120
+ position: absolute;
121
+ width: 0;
122
+ height: 0;
123
+ border: var(--bubble-arrow-size) solid transparent;
124
+ }
125
+
126
+ /* Arrow: top placement (popover below trigger) */
127
+ .vd-bubble-content[data-placement="bottom"]::before {
128
+ bottom: 100%;
129
+ left: 50%;
130
+ transform: translateX(-50%);
131
+ border-bottom-color: var(--bubble-border-color);
132
+ }
133
+
134
+ .vd-bubble-content[data-placement="top"]::before {
135
+ top: 100%;
136
+ left: 50%;
137
+ transform: translateX(-50%);
138
+ border-top-color: var(--bubble-border-color);
139
+ }
140
+
141
+ .vd-bubble-content[data-placement="left"]::before {
142
+ left: 100%;
143
+ top: 50%;
144
+ transform: translateY(-50%);
145
+ border-left-color: var(--bubble-border-color);
146
+ }
147
+
148
+ .vd-bubble-content[data-placement="right"]::before {
149
+ right: 100%;
150
+ top: 50%;
151
+ transform: translateY(-50%);
152
+ border-right-color: var(--bubble-border-color);
153
+ }
154
+
155
+ /* ========== Size Variants ========== */
156
+
157
+ .vd-bubble-sm .vd-bubble-body {
158
+ --bubble-padding: 0.5rem; /* 8px - fib */
159
+ --bubble-font-size: var(--font-size-xs, 0.75rem);
160
+ }
161
+
162
+ .vd-bubble-lg .vd-bubble-body {
163
+ --bubble-padding: 1.3125rem; /* 21px - fib */
164
+ --bubble-max-width: 34rem;
165
+ }
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Vanduo Framework - Datepicker
3
+ * Calendar popup for date selection
4
+ */
5
+
6
+ :root {
7
+ /* Datepicker Colors */
8
+ --dp-bg: var(--card-bg, #fff);
9
+ --dp-border-color: var(--border-color, #dee2e6);
10
+ --dp-shadow: 0 0.25rem 0.8125rem rgba(0, 0, 0, 0.12); /* 4px 13px fib */
11
+ --dp-header-bg: var(--color-primary, #0d6efd);
12
+ --dp-header-color: #fff;
13
+ --dp-day-hover-bg: var(--bg-secondary, #f8f9fa);
14
+ --dp-day-selected-bg: var(--color-primary, #0d6efd);
15
+ --dp-day-selected-color: #fff;
16
+ --dp-day-today-color: var(--color-primary, #0d6efd);
17
+ --dp-day-outside-color: var(--text-muted, #6c757d);
18
+ --dp-day-disabled-color: var(--text-disabled, #adb5bd);
19
+
20
+ /* Datepicker Spacing (Fibonacci) */
21
+ --dp-padding: 0.5rem; /* 8px - fib */
22
+ --dp-cell-size: 2.25rem; /* 36px */
23
+ --dp-gap: 2px;
24
+ --dp-border-radius: var(--border-radius, 0.5rem);
25
+
26
+ /* Datepicker Z-index */
27
+ --dp-z-index: 1055;
28
+ }
29
+
30
+ [data-theme="dark"] {
31
+ --dp-bg: var(--card-bg, #2d2d44);
32
+ --dp-border-color: var(--border-color, #3d3d5c);
33
+ --dp-day-hover-bg: var(--bg-primary, #1a1a2e);
34
+ --dp-shadow: 0 0.25rem 0.8125rem rgba(0, 0, 0, 0.3);
35
+ }
36
+
37
+ @media (prefers-color-scheme: dark) {
38
+ :root:not([data-theme]) {
39
+ --dp-bg: var(--card-bg, #2d2d44);
40
+ --dp-border-color: var(--border-color, #3d3d5c);
41
+ --dp-day-hover-bg: var(--bg-primary, #1a1a2e);
42
+ --dp-shadow: 0 0.25rem 0.8125rem rgba(0, 0, 0, 0.3);
43
+ }
44
+ }
45
+
46
+ /* ========== Calendar Popup ========== */
47
+
48
+ .vd-datepicker-popup {
49
+ position: absolute;
50
+ z-index: var(--dp-z-index);
51
+ background: var(--dp-bg);
52
+ border: 1px solid var(--dp-border-color);
53
+ border-radius: var(--dp-border-radius);
54
+ box-shadow: var(--dp-shadow);
55
+ padding: var(--dp-padding);
56
+ display: none;
57
+ min-width: 17rem;
58
+ }
59
+
60
+ .vd-datepicker-popup.is-open {
61
+ display: block;
62
+ }
63
+
64
+ /* ========== Header ========== */
65
+
66
+ .vd-datepicker-header {
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: space-between;
70
+ padding: 0.3125rem; /* 5px - fib */
71
+ margin-bottom: 0.3125rem;
72
+ }
73
+
74
+ .vd-datepicker-title {
75
+ font-weight: 600;
76
+ font-size: var(--font-size-base, 1rem);
77
+ cursor: pointer;
78
+ }
79
+
80
+ .vd-datepicker-title:hover {
81
+ color: var(--dp-day-today-color);
82
+ }
83
+
84
+ .vd-datepicker-prev,
85
+ .vd-datepicker-next {
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ width: 1.75rem;
90
+ height: 1.75rem;
91
+ padding: 0;
92
+ border: none;
93
+ border-radius: 50%;
94
+ background: transparent;
95
+ cursor: pointer;
96
+ font-size: 1rem;
97
+ color: var(--text-primary, #212529);
98
+ transition: background 0.15s ease;
99
+ }
100
+
101
+ .vd-datepicker-prev:hover,
102
+ .vd-datepicker-next:hover {
103
+ background: var(--dp-day-hover-bg);
104
+ }
105
+
106
+ /* ========== Weekday Headers ========== */
107
+
108
+ .vd-datepicker-weekdays {
109
+ display: grid;
110
+ grid-template-columns: repeat(7, 1fr);
111
+ gap: var(--dp-gap);
112
+ text-align: center;
113
+ font-size: 0.75rem;
114
+ font-weight: 600;
115
+ color: var(--text-muted, #6c757d);
116
+ padding-bottom: 0.25rem;
117
+ }
118
+
119
+ /* ========== Days Grid ========== */
120
+
121
+ .vd-datepicker-days {
122
+ display: grid;
123
+ grid-template-columns: repeat(7, 1fr);
124
+ gap: var(--dp-gap);
125
+ }
126
+
127
+ .vd-datepicker-day {
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ width: var(--dp-cell-size);
132
+ height: var(--dp-cell-size);
133
+ border: none;
134
+ border-radius: 50%;
135
+ background: transparent;
136
+ cursor: pointer;
137
+ font-size: 0.875rem;
138
+ transition: background 0.15s ease, color 0.15s ease;
139
+ padding: 0;
140
+ }
141
+
142
+ .vd-datepicker-day:hover {
143
+ background: var(--dp-day-hover-bg);
144
+ }
145
+
146
+ .vd-datepicker-day.is-today {
147
+ color: var(--dp-day-today-color);
148
+ font-weight: 700;
149
+ }
150
+
151
+ .vd-datepicker-day.is-selected {
152
+ background: var(--dp-day-selected-bg);
153
+ color: var(--dp-day-selected-color);
154
+ font-weight: 600;
155
+ }
156
+
157
+ .vd-datepicker-day.is-outside {
158
+ color: var(--dp-day-outside-color);
159
+ }
160
+
161
+ .vd-datepicker-day.is-disabled {
162
+ color: var(--dp-day-disabled-color);
163
+ cursor: not-allowed;
164
+ pointer-events: none;
165
+ }
166
+
167
+ /* ========== Range ========== */
168
+
169
+ .vd-datepicker-day.is-range-start {
170
+ border-radius: 50% 0 0 50%;
171
+ background: var(--dp-day-selected-bg);
172
+ color: var(--dp-day-selected-color);
173
+ }
174
+
175
+ .vd-datepicker-day.is-range-end {
176
+ border-radius: 0 50% 50% 0;
177
+ background: var(--dp-day-selected-bg);
178
+ color: var(--dp-day-selected-color);
179
+ }
180
+
181
+ .vd-datepicker-day.is-in-range {
182
+ background: rgba(13, 110, 253, 0.1);
183
+ border-radius: 0;
184
+ }
185
+
186
+ /* ========== Month/Year Picker ========== */
187
+
188
+ .vd-datepicker-months,
189
+ .vd-datepicker-years {
190
+ display: grid;
191
+ grid-template-columns: repeat(3, 1fr);
192
+ gap: 0.25rem;
193
+ padding: 0.25rem;
194
+ }
195
+
196
+ .vd-datepicker-month-btn,
197
+ .vd-datepicker-year-btn {
198
+ padding: 0.5rem;
199
+ border: none;
200
+ border-radius: var(--dp-border-radius);
201
+ background: transparent;
202
+ cursor: pointer;
203
+ text-align: center;
204
+ transition: background 0.15s ease;
205
+ }
206
+
207
+ .vd-datepicker-month-btn:hover,
208
+ .vd-datepicker-year-btn:hover {
209
+ background: var(--dp-day-hover-bg);
210
+ }
211
+
212
+ .vd-datepicker-month-btn.is-selected,
213
+ .vd-datepicker-year-btn.is-selected {
214
+ background: var(--dp-day-selected-bg);
215
+ color: var(--dp-day-selected-color);
216
+ }