@omg-dev/pwa 0.4.24

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/src/styles.ts ADDED
@@ -0,0 +1,213 @@
1
+ // @omg-dev/pwa — self-contained stylesheet, injected at first mount.
2
+ //
3
+ // Deliberately NOT Tailwind: this UI must render correctly inside any user
4
+ // app (themed or bare) and inside the omg dashboard. Every color reads the
5
+ // host's shadcn CSS variables first (--card, --primary, …) and falls back to
6
+ // neutral defaults with a prefers-color-scheme dark variant, so the sheet
7
+ // looks native in themed apps and still presentable in unthemed ones.
8
+
9
+ export const STYLE_ID = "vibes-pwa-styles"
10
+
11
+ export function ensureStyles() {
12
+ if (typeof document === "undefined") return
13
+ if (document.getElementById(STYLE_ID)) return
14
+ const el = document.createElement("style")
15
+ el.id = STYLE_ID
16
+ el.textContent = CSS
17
+ document.head.appendChild(el)
18
+ }
19
+
20
+ const CSS = `
21
+ .vpwa {
22
+ --vpwa-bg: #ffffff;
23
+ --vpwa-fg: #18181b;
24
+ --vpwa-muted: #71717a;
25
+ --vpwa-surface: #f4f4f5;
26
+ --vpwa-border: rgba(0, 0, 0, 0.1);
27
+ --vpwa-accent: #2563eb;
28
+ --vpwa-accent-fg: #ffffff;
29
+ font-family: inherit;
30
+ box-sizing: border-box;
31
+ }
32
+ .vpwa *, .vpwa *::before, .vpwa *::after { box-sizing: border-box; }
33
+ @media (prefers-color-scheme: dark) {
34
+ .vpwa {
35
+ --vpwa-bg: #1c1c1e;
36
+ --vpwa-fg: #f4f4f5;
37
+ --vpwa-muted: #a1a1aa;
38
+ --vpwa-surface: #2c2c2e;
39
+ --vpwa-border: rgba(255, 255, 255, 0.12);
40
+ --vpwa-accent: #3b82f6;
41
+ }
42
+ }
43
+
44
+ /* ── overlay + sheet ─────────────────────────────────────────────────── */
45
+ .vpwa-overlay {
46
+ position: fixed; inset: 0; z-index: 2147483000;
47
+ display: flex; align-items: flex-end; justify-content: center;
48
+ }
49
+ .vpwa-backdrop {
50
+ position: absolute; inset: 0;
51
+ background: rgba(0, 0, 0, 0.5);
52
+ opacity: 0; transition: opacity 0.25s ease;
53
+ }
54
+ .vpwa-open .vpwa-backdrop { opacity: 1; }
55
+ .vpwa-sheet {
56
+ position: relative; width: 100%; max-width: 430px;
57
+ background: var(--card, var(--vpwa-bg));
58
+ color: var(--card-foreground, var(--vpwa-fg));
59
+ border: 1px solid var(--border, var(--vpwa-border)); border-bottom: none;
60
+ border-radius: 24px 24px 0 0;
61
+ box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.2);
62
+ padding: 8px 24px calc(24px + env(safe-area-inset-bottom));
63
+ transform: translateY(100%);
64
+ transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);
65
+ }
66
+ .vpwa-open .vpwa-sheet { transform: translateY(0); }
67
+ @media (min-width: 640px) {
68
+ .vpwa-overlay { align-items: center; padding: 24px; }
69
+ .vpwa-sheet {
70
+ border-radius: 24px; border-bottom: 1px solid var(--border, var(--vpwa-border));
71
+ padding: 24px; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.25);
72
+ transform: translateY(12px); opacity: 0;
73
+ transition: transform 0.25s ease, opacity 0.25s ease;
74
+ }
75
+ .vpwa-open .vpwa-sheet { transform: translateY(0); opacity: 1; }
76
+ .vpwa-handle { display: none; }
77
+ }
78
+ .vpwa-handle {
79
+ width: 40px; height: 4px; border-radius: 999px;
80
+ background: var(--muted-foreground, var(--vpwa-muted));
81
+ opacity: 0.25; margin: 4px auto 16px;
82
+ }
83
+ .vpwa-x {
84
+ position: absolute; top: 14px; right: 14px;
85
+ width: 32px; height: 32px; border-radius: 999px;
86
+ display: flex; align-items: center; justify-content: center;
87
+ border: none; background: transparent; cursor: pointer;
88
+ color: var(--muted-foreground, var(--vpwa-muted));
89
+ }
90
+ .vpwa-x:hover { background: var(--muted, var(--vpwa-surface)); }
91
+
92
+ .vpwa-title {
93
+ margin: 0 24px 4px 0; font-size: 17px; font-weight: 600;
94
+ letter-spacing: -0.01em; line-height: 1.3;
95
+ }
96
+ .vpwa-sub {
97
+ margin: 0 0 20px; font-size: 13px; line-height: 1.45;
98
+ color: var(--muted-foreground, var(--vpwa-muted));
99
+ }
100
+
101
+ /* ── steps ───────────────────────────────────────────────────────────── */
102
+ .vpwa-steps { display: flex; flex-direction: column; gap: 16px; margin: 0; padding: 0; list-style: none; }
103
+ .vpwa-step { display: flex; flex-direction: column; gap: 8px; }
104
+ .vpwa-stephead { display: flex; align-items: baseline; gap: 10px; }
105
+ .vpwa-stepnum {
106
+ font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
107
+ color: var(--muted-foreground, var(--vpwa-muted));
108
+ }
109
+ .vpwa-steptext { font-size: 14px; font-weight: 500; }
110
+ .vpwa-stepcap { font-weight: 400; color: var(--muted-foreground, var(--vpwa-muted)); }
111
+
112
+ /* ── mocks ───────────────────────────────────────────────────────────── */
113
+ .vpwa-toolbar {
114
+ display: flex; align-items: center; justify-content: space-between; gap: 16px;
115
+ background: var(--muted, var(--vpwa-surface));
116
+ border-radius: 12px; padding: 10px 16px;
117
+ color: var(--muted-foreground, var(--vpwa-muted));
118
+ }
119
+ .vpwa-toolbar svg { display: block; }
120
+ .vpwa-omnibox {
121
+ display: flex; align-items: center; gap: 10px;
122
+ background: var(--muted, var(--vpwa-surface));
123
+ border-radius: 999px; padding: 8px 14px;
124
+ color: var(--muted-foreground, var(--vpwa-muted));
125
+ font-size: 13px;
126
+ }
127
+ .vpwa-omnibox-url { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.7; }
128
+ .vpwa-sheetrow {
129
+ display: flex; align-items: center; justify-content: space-between; gap: 12px;
130
+ background: var(--background, var(--vpwa-bg));
131
+ border: 1px solid var(--border, var(--vpwa-border));
132
+ border-radius: 12px; padding: 11px 14px;
133
+ font-size: 14px; font-weight: 500;
134
+ }
135
+ .vpwa-confirm {
136
+ display: flex; align-items: center; justify-content: space-between;
137
+ background: var(--muted, var(--vpwa-surface));
138
+ border-radius: 12px; padding: 11px 16px; font-size: 14px;
139
+ color: var(--muted-foreground, var(--vpwa-muted));
140
+ }
141
+ .vpwa-confirm b { color: var(--primary, var(--vpwa-accent)); font-weight: 600; }
142
+ .vpwa-target {
143
+ color: var(--primary, var(--vpwa-accent));
144
+ animation: vpwa-pulse 2s ease-in-out infinite;
145
+ }
146
+ @keyframes vpwa-pulse {
147
+ 0%, 100% { opacity: 1; }
148
+ 50% { opacity: 0.4; }
149
+ }
150
+ @media (prefers-reduced-motion: reduce) {
151
+ .vpwa-target { animation: none; }
152
+ .vpwa-sheet, .vpwa-backdrop, .vpwa-banner { transition: none; }
153
+ }
154
+
155
+ /* ── buttons ─────────────────────────────────────────────────────────── */
156
+ .vpwa-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 20px; }
157
+ .vpwa-btn {
158
+ width: 100%; height: 44px; border-radius: 12px; border: none; cursor: pointer;
159
+ background: var(--primary, var(--vpwa-accent));
160
+ color: var(--primary-foreground, var(--vpwa-accent-fg));
161
+ font-size: 15px; font-weight: 600; font-family: inherit;
162
+ }
163
+ .vpwa-btn:active { opacity: 0.85; }
164
+ .vpwa-btn-ghost {
165
+ width: 100%; height: 40px; border-radius: 12px; border: none; cursor: pointer;
166
+ background: transparent; font-family: inherit;
167
+ color: var(--muted-foreground, var(--vpwa-muted));
168
+ font-size: 14px; font-weight: 500;
169
+ }
170
+ .vpwa-btn-ghost:hover { background: var(--muted, var(--vpwa-surface)); }
171
+
172
+ /* ── banner (floating / inline prompt) ───────────────────────────────── */
173
+ .vpwa-banner {
174
+ display: flex; align-items: center; gap: 12px;
175
+ background: var(--card, var(--vpwa-bg));
176
+ color: var(--card-foreground, var(--vpwa-fg));
177
+ border: 1px solid var(--border, var(--vpwa-border));
178
+ border-radius: 16px; padding: 12px 12px 12px 14px;
179
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
180
+ }
181
+ .vpwa-banner-floating {
182
+ position: fixed; left: 16px; right: 16px;
183
+ bottom: calc(16px + env(safe-area-inset-bottom));
184
+ z-index: 2147482999; max-width: 430px; margin: 0 auto;
185
+ box-shadow: 0 12px 36px rgba(0, 0, 0, 0.2);
186
+ transform: translateY(calc(100% + 32px));
187
+ transition: transform 0.35s cubic-bezier(0.32, 0.72, 0, 1);
188
+ }
189
+ .vpwa-banner-floating.vpwa-in { transform: translateY(0); }
190
+ .vpwa-chip {
191
+ width: 38px; height: 38px; border-radius: 12px; flex-shrink: 0;
192
+ display: flex; align-items: center; justify-content: center;
193
+ background: color-mix(in srgb, var(--primary, var(--vpwa-accent)) 12%, transparent);
194
+ color: var(--primary, var(--vpwa-accent));
195
+ }
196
+ .vpwa-banner-text { flex: 1; min-width: 0; }
197
+ .vpwa-banner-title {
198
+ margin: 0; font-size: 14px; font-weight: 600;
199
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
200
+ }
201
+ .vpwa-banner-cap {
202
+ margin: 0; font-size: 12px;
203
+ color: var(--muted-foreground, var(--vpwa-muted));
204
+ }
205
+ .vpwa-btn-sm {
206
+ height: 32px; padding: 0 14px; border-radius: 999px; border: none;
207
+ cursor: pointer; flex-shrink: 0; font-family: inherit;
208
+ background: var(--primary, var(--vpwa-accent));
209
+ color: var(--primary-foreground, var(--vpwa-accent-fg));
210
+ font-size: 13px; font-weight: 600;
211
+ }
212
+ .vpwa-banner .vpwa-x { position: static; width: 28px; height: 28px; flex-shrink: 0; }
213
+ `