@spacesync/client 0.1.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.
- package/README.md +39 -0
- package/dist/analog-clock-picker.d.ts +10 -0
- package/dist/analog-clock-picker.js +408 -0
- package/dist/analog-clock-picker.js.map +1 -0
- package/dist/api.d.ts +222 -0
- package/dist/api.js +167 -0
- package/dist/api.js.map +1 -0
- package/dist/app-modal.d.ts +25 -0
- package/dist/app-modal.js +145 -0
- package/dist/app-modal.js.map +1 -0
- package/dist/app-shell-mobile-nav.d.ts +29 -0
- package/dist/app-shell-mobile-nav.js +122 -0
- package/dist/app-shell-mobile-nav.js.map +1 -0
- package/dist/app-web-shell.d.ts +20 -0
- package/dist/app-web-shell.js +45 -0
- package/dist/app-web-shell.js.map +1 -0
- package/dist/booking-schedule-calendars.d.ts +95 -0
- package/dist/booking-schedule-calendars.js +1343 -0
- package/dist/booking-schedule-calendars.js.map +1 -0
- package/dist/chat-stick-to-bottom.d.ts +22 -0
- package/dist/chat-stick-to-bottom.js +190 -0
- package/dist/chat-stick-to-bottom.js.map +1 -0
- package/dist/detail-page-header.d.ts +16 -0
- package/dist/detail-page-header.js +220 -0
- package/dist/detail-page-header.js.map +1 -0
- package/dist/dialog-CIdvylPK.d.ts +16 -0
- package/dist/errors-D1niseaa.d.ts +34 -0
- package/dist/file-picker-field.d.ts +23 -0
- package/dist/file-picker-field.js +165 -0
- package/dist/file-picker-field.js.map +1 -0
- package/dist/file-viewer-dialog.d.ts +15 -0
- package/dist/file-viewer-dialog.js +387 -0
- package/dist/file-viewer-dialog.js.map +1 -0
- package/dist/floor-switcher.d.ts +14 -0
- package/dist/floor-switcher.js +416 -0
- package/dist/floor-switcher.js.map +1 -0
- package/dist/forms.d.ts +52 -0
- package/dist/forms.js +66 -0
- package/dist/forms.js.map +1 -0
- package/dist/image-picker-field.d.ts +11 -0
- package/dist/image-picker-field.js +135 -0
- package/dist/image-picker-field.js.map +1 -0
- package/dist/layout-canvas-view.d.ts +57 -0
- package/dist/layout-canvas-view.js +974 -0
- package/dist/layout-canvas-view.js.map +1 -0
- package/dist/lib/dateDisplay.d.ts +24 -0
- package/dist/lib/dateDisplay.js +84 -0
- package/dist/lib/dateDisplay.js.map +1 -0
- package/dist/live-resource-meta.d.ts +11 -0
- package/dist/live-resource-meta.js +27 -0
- package/dist/live-resource-meta.js.map +1 -0
- package/dist/live-space-pulse-dot.d.ts +8 -0
- package/dist/live-space-pulse-dot.js +18 -0
- package/dist/live-space-pulse-dot.js.map +1 -0
- package/dist/notification-sidebar-preview.d.ts +37 -0
- package/dist/notification-sidebar-preview.js +121 -0
- package/dist/notification-sidebar-preview.js.map +1 -0
- package/dist/page-list-chrome.d.ts +124 -0
- package/dist/page-list-chrome.js +970 -0
- package/dist/page-list-chrome.js.map +1 -0
- package/dist/platform-support-message-composer.d.ts +38 -0
- package/dist/platform-support-message-composer.js +446 -0
- package/dist/platform-support-message-composer.js.map +1 -0
- package/dist/shell-sidebar-nav.d.ts +16 -0
- package/dist/shell-sidebar-nav.js +69 -0
- package/dist/shell-sidebar-nav.js.map +1 -0
- package/dist/shell-theme.d.ts +6 -0
- package/dist/shell-theme.js +9 -0
- package/dist/shell-theme.js.map +1 -0
- package/dist/shell-top-bar-chrome.d.ts +39 -0
- package/dist/shell-top-bar-chrome.js +105 -0
- package/dist/shell-top-bar-chrome.js.map +1 -0
- package/dist/shell-top-bar.d.ts +16 -0
- package/dist/shell-top-bar.js +71 -0
- package/dist/shell-top-bar.js.map +1 -0
- package/dist/styles/theme.css +223 -0
- package/dist/styles/theme.css.map +1 -0
- package/dist/styles/theme.d.ts +2 -0
- package/dist/support-presence-status.d.ts +11 -0
- package/dist/support-presence-status.js +92 -0
- package/dist/support-presence-status.js.map +1 -0
- package/dist/theme-appearance-control.d.ts +5 -0
- package/dist/theme-appearance-control.js +114 -0
- package/dist/theme-appearance-control.js.map +1 -0
- package/dist/theme-boot-script.d.ts +4 -0
- package/dist/theme-boot-script.js +9 -0
- package/dist/theme-boot-script.js.map +1 -0
- package/dist/theme-provider.d.ts +9 -0
- package/dist/theme-provider.js +25 -0
- package/dist/theme-provider.js.map +1 -0
- package/dist/ui.d.ts +765 -0
- package/dist/ui.js +5637 -0
- package/dist/ui.js.map +1 -0
- package/dist/use-client-pagination.d.ts +22 -0
- package/dist/use-client-pagination.js +51 -0
- package/dist/use-client-pagination.js.map +1 -0
- package/dist/use-client-sort.d.ts +20 -0
- package/dist/use-client-sort.js +41 -0
- package/dist/use-client-sort.js.map +1 -0
- package/package.json +208 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
@import "@fontsource-variable/inter";
|
|
2
|
+
|
|
3
|
+
/* src/styles/theme.css */
|
|
4
|
+
@custom-variant dark (&:is(.dark *));
|
|
5
|
+
:root {
|
|
6
|
+
--font-size: 16px;
|
|
7
|
+
--background: #ffffff;
|
|
8
|
+
--foreground: oklch(0.145 0 0);
|
|
9
|
+
--card: #ffffff;
|
|
10
|
+
--card-foreground: oklch(0.145 0 0);
|
|
11
|
+
--popover: #030213;
|
|
12
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
13
|
+
--primary: #030213;
|
|
14
|
+
--primary-foreground: oklch(1 0 0);
|
|
15
|
+
--secondary: oklch(0.95 0.0058 264.53);
|
|
16
|
+
--secondary-foreground: #030213;
|
|
17
|
+
--muted: #f5f5f7;
|
|
18
|
+
--muted-foreground: #8a8a9a;
|
|
19
|
+
--accent: #f1f2f4;
|
|
20
|
+
--accent-foreground: #030213;
|
|
21
|
+
--destructive: #d4183d;
|
|
22
|
+
--destructive-foreground: #ffffff;
|
|
23
|
+
--border: #eceef2;
|
|
24
|
+
--input: #eceef2;
|
|
25
|
+
--input-background: #f7f7f8;
|
|
26
|
+
--switch-background: #cbced4;
|
|
27
|
+
--font-weight-medium: 500;
|
|
28
|
+
--font-weight-normal: 400;
|
|
29
|
+
--ring: oklch(0.708 0 0);
|
|
30
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
31
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
32
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
33
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
34
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
35
|
+
--radius: 0.625rem;
|
|
36
|
+
--sidebar: #f5f5f7;
|
|
37
|
+
--sidebar-foreground: #13131a;
|
|
38
|
+
--sidebar-primary: #13131a;
|
|
39
|
+
--sidebar-primary-foreground: #f5f5f7;
|
|
40
|
+
--sidebar-accent: #eceef2;
|
|
41
|
+
--sidebar-accent-foreground: #13131a;
|
|
42
|
+
--sidebar-border: #e0e0e5;
|
|
43
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
44
|
+
--scrollbar-thumb: oklch(0.55 0 0 / 0.28);
|
|
45
|
+
--scrollbar-thumb-hover: oklch(0.45 0 0 / 0.4);
|
|
46
|
+
}
|
|
47
|
+
:root[data-shell-theme=light],
|
|
48
|
+
:root:not([data-shell-theme]) {
|
|
49
|
+
--sidebar: #f5f5f7;
|
|
50
|
+
--sidebar-foreground: #13131a;
|
|
51
|
+
--sidebar-primary: #13131a;
|
|
52
|
+
--sidebar-primary-foreground: #f5f5f7;
|
|
53
|
+
--sidebar-accent: #eceef2;
|
|
54
|
+
--sidebar-accent-foreground: #13131a;
|
|
55
|
+
--sidebar-border: #e0e0e5;
|
|
56
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
57
|
+
}
|
|
58
|
+
:root[data-shell-theme=dark] {
|
|
59
|
+
--sidebar: #13131a;
|
|
60
|
+
--sidebar-foreground: oklch(0.93 0 0);
|
|
61
|
+
--sidebar-primary: oklch(0.93 0 0);
|
|
62
|
+
--sidebar-primary-foreground: #13131a;
|
|
63
|
+
--sidebar-accent: oklch(0.24 0.01 264);
|
|
64
|
+
--sidebar-accent-foreground: oklch(0.95 0 0);
|
|
65
|
+
--sidebar-border: oklch(0.3 0.01 264);
|
|
66
|
+
--sidebar-ring: oklch(0.55 0 0);
|
|
67
|
+
}
|
|
68
|
+
.dark {
|
|
69
|
+
--background: oklch(0.145 0 0);
|
|
70
|
+
--foreground: oklch(0.985 0 0);
|
|
71
|
+
--card: oklch(0.145 0 0);
|
|
72
|
+
--card-foreground: oklch(0.985 0 0);
|
|
73
|
+
--popover: oklch(0.145 0 0);
|
|
74
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
75
|
+
--primary: oklch(0.985 0 0);
|
|
76
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
77
|
+
--secondary: oklch(0.269 0 0);
|
|
78
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
79
|
+
--muted: oklch(0.269 0 0);
|
|
80
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
81
|
+
--accent: oklch(0.269 0 0);
|
|
82
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
83
|
+
--destructive: oklch(0.396 0.141 25.723);
|
|
84
|
+
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
85
|
+
--border: oklch(0.269 0 0);
|
|
86
|
+
--input: oklch(0.269 0 0);
|
|
87
|
+
--ring: oklch(0.439 0 0);
|
|
88
|
+
--font-weight-medium: 500;
|
|
89
|
+
--font-weight-normal: 400;
|
|
90
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
91
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
92
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
93
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
94
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
95
|
+
--scrollbar-thumb: oklch(0.985 0 0 / 0.22);
|
|
96
|
+
--scrollbar-thumb-hover: oklch(0.985 0 0 / 0.35);
|
|
97
|
+
}
|
|
98
|
+
.dark[data-shell-theme=light] {
|
|
99
|
+
--sidebar: #f5f5f7;
|
|
100
|
+
--sidebar-foreground: #13131a;
|
|
101
|
+
--sidebar-primary: #13131a;
|
|
102
|
+
--sidebar-primary-foreground: #f5f5f7;
|
|
103
|
+
--sidebar-accent: #eceef2;
|
|
104
|
+
--sidebar-accent-foreground: #13131a;
|
|
105
|
+
--sidebar-border: #e0e0e5;
|
|
106
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
107
|
+
}
|
|
108
|
+
.dark[data-shell-theme=dark] {
|
|
109
|
+
--sidebar: oklch(0.205 0 0);
|
|
110
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
111
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
112
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
113
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
114
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
115
|
+
--sidebar-border: oklch(0.269 0 0);
|
|
116
|
+
--sidebar-ring: oklch(0.439 0 0);
|
|
117
|
+
}
|
|
118
|
+
@theme inline { --font-sans: "Inter Variable", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-border: var(--border); --color-input: var(--input); --color-input-background: var(--input-background); --color-switch-background: var(--switch-background); --color-ring: var(--ring); --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); }
|
|
119
|
+
@layer base {
|
|
120
|
+
* {
|
|
121
|
+
@apply border-border outline-ring/50;
|
|
122
|
+
}
|
|
123
|
+
body {
|
|
124
|
+
@apply bg-background text-foreground font-sans;
|
|
125
|
+
}
|
|
126
|
+
html {
|
|
127
|
+
font-size: var(--font-size);
|
|
128
|
+
}
|
|
129
|
+
h1 {
|
|
130
|
+
font-size: var(--text-2xl);
|
|
131
|
+
font-weight: var(--font-weight-medium);
|
|
132
|
+
line-height: 1.5;
|
|
133
|
+
}
|
|
134
|
+
h2 {
|
|
135
|
+
font-size: var(--text-xl);
|
|
136
|
+
font-weight: var(--font-weight-medium);
|
|
137
|
+
line-height: 1.5;
|
|
138
|
+
}
|
|
139
|
+
h3 {
|
|
140
|
+
font-size: var(--text-lg);
|
|
141
|
+
font-weight: var(--font-weight-medium);
|
|
142
|
+
line-height: 1.5;
|
|
143
|
+
}
|
|
144
|
+
h4 {
|
|
145
|
+
font-size: var(--text-base);
|
|
146
|
+
font-weight: var(--font-weight-medium);
|
|
147
|
+
line-height: 1.5;
|
|
148
|
+
}
|
|
149
|
+
label {
|
|
150
|
+
font-size: var(--text-base);
|
|
151
|
+
font-weight: var(--font-weight-medium);
|
|
152
|
+
line-height: 1.5;
|
|
153
|
+
}
|
|
154
|
+
button {
|
|
155
|
+
font-size: var(--text-base);
|
|
156
|
+
font-weight: var(--font-weight-medium);
|
|
157
|
+
line-height: 1.5;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
}
|
|
160
|
+
button:disabled {
|
|
161
|
+
cursor: not-allowed;
|
|
162
|
+
}
|
|
163
|
+
input {
|
|
164
|
+
font-size: var(--text-base);
|
|
165
|
+
font-weight: var(--font-weight-normal);
|
|
166
|
+
line-height: 1.5;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
@layer components {
|
|
170
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-title] .text-foreground,
|
|
171
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-actions] .text-foreground {
|
|
172
|
+
color: var(--sidebar-foreground) !important;
|
|
173
|
+
}
|
|
174
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-title] .text-muted-foreground,
|
|
175
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-actions] .text-muted-foreground {
|
|
176
|
+
color: color-mix(in oklch, var(--sidebar-foreground) 62%, transparent) !important;
|
|
177
|
+
}
|
|
178
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-actions] :is([data-slot=button], [data-shell-top-bar-action]):hover,
|
|
179
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-actions] :is([data-slot=button], [data-shell-top-bar-action]):active {
|
|
180
|
+
color: var(--sidebar-foreground) !important;
|
|
181
|
+
}
|
|
182
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-actions] :is([data-slot=button], [data-shell-top-bar-action]).border-sidebar-border:hover,
|
|
183
|
+
:root[data-shell-theme=dark] [data-slot=shell-top-bar-actions] :is([data-slot=button], [data-shell-top-bar-action]).border-sidebar-border:active {
|
|
184
|
+
background-color: color-mix(in oklch, var(--sidebar-foreground) 12%, var(--sidebar-accent)) !important;
|
|
185
|
+
border-color: color-mix(in oklch, var(--sidebar-foreground) 25%, var(--sidebar-border)) !important;
|
|
186
|
+
}
|
|
187
|
+
:root[data-shell-theme=light] [data-slot=shell-top-bar-actions] :is([data-slot=button], [data-shell-top-bar-action]).border-sidebar-border:hover,
|
|
188
|
+
:root[data-shell-theme=light] [data-slot=shell-top-bar-actions] :is([data-slot=button], [data-shell-top-bar-action]).border-sidebar-border:active {
|
|
189
|
+
background-color: color-mix(in oklch, var(--sidebar-foreground) 6%, var(--sidebar-accent)) !important;
|
|
190
|
+
border-color: color-mix(in oklch, var(--sidebar-foreground) 14%, var(--sidebar-border)) !important;
|
|
191
|
+
color: var(--sidebar-foreground) !important;
|
|
192
|
+
}
|
|
193
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]),
|
|
194
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto) {
|
|
195
|
+
scrollbar-width: thin;
|
|
196
|
+
scrollbar-color: var(--scrollbar-thumb) transparent;
|
|
197
|
+
}
|
|
198
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content])::-webkit-scrollbar,
|
|
199
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar {
|
|
200
|
+
width: 6px;
|
|
201
|
+
height: 6px;
|
|
202
|
+
}
|
|
203
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content])::-webkit-scrollbar-track,
|
|
204
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar-track {
|
|
205
|
+
background: transparent;
|
|
206
|
+
}
|
|
207
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content])::-webkit-scrollbar-thumb,
|
|
208
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar-thumb {
|
|
209
|
+
background-color: var(--scrollbar-thumb);
|
|
210
|
+
border-radius: 9999px;
|
|
211
|
+
}
|
|
212
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content])::-webkit-scrollbar-thumb:hover,
|
|
213
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar-thumb:hover {
|
|
214
|
+
background-color: var(--scrollbar-thumb-hover);
|
|
215
|
+
}
|
|
216
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) [data-slot=scroll-area-thumb] {
|
|
217
|
+
background-color: var(--scrollbar-thumb);
|
|
218
|
+
}
|
|
219
|
+
:is([data-slot=popover-content], [data-slot=hover-card-content], [data-slot=dropdown-menu-content], [data-slot=dropdown-menu-sub-content], [data-slot=select-content], [data-slot=context-menu-content], [data-slot=context-menu-sub-content], [data-slot=menubar-content], [data-slot=menubar-sub-content]) [data-slot=scroll-area-thumb]:hover {
|
|
220
|
+
background-color: var(--scrollbar-thumb-hover);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/*# sourceMappingURL=theme.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/styles/theme.css"],"sourcesContent":["@import \"@fontsource-variable/inter\";\n\n@custom-variant dark (&:is(.dark *));\n\n:root {\n --font-size: 16px;\n --background: #ffffff;\n --foreground: oklch(0.145 0 0);\n --card: #ffffff;\n --card-foreground: oklch(0.145 0 0);\n --popover: #030213;\n --popover-foreground: oklch(0.985 0 0);\n --primary: #030213;\n --primary-foreground: oklch(1 0 0);\n --secondary: oklch(0.95 0.0058 264.53);\n --secondary-foreground: #030213;\n --muted: #f5f5f7;\n --muted-foreground: #8a8a9a;\n --accent: #f1f2f4;\n --accent-foreground: #030213;\n --destructive: #d4183d;\n --destructive-foreground: #ffffff;\n --border: #eceef2;\n --input: #eceef2;\n --input-background: #f7f7f8;\n --switch-background: #cbced4;\n --font-weight-medium: 500;\n --font-weight-normal: 400;\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.646 0.222 41.116);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n --radius: 0.625rem;\n --sidebar: #f5f5f7;\n --sidebar-foreground: #13131a;\n --sidebar-primary: #13131a;\n --sidebar-primary-foreground: #f5f5f7;\n --sidebar-accent: #eceef2;\n --sidebar-accent-foreground: #13131a;\n --sidebar-border: #e0e0e5;\n --sidebar-ring: oklch(0.708 0 0);\n --scrollbar-thumb: oklch(0.55 0 0 / 0.28);\n --scrollbar-thumb-hover: oklch(0.45 0 0 / 0.4);\n}\n\n:root[data-shell-theme=\"light\"],\n:root:not([data-shell-theme]) {\n --sidebar: #f5f5f7;\n --sidebar-foreground: #13131a;\n --sidebar-primary: #13131a;\n --sidebar-primary-foreground: #f5f5f7;\n --sidebar-accent: #eceef2;\n --sidebar-accent-foreground: #13131a;\n --sidebar-border: #e0e0e5;\n --sidebar-ring: oklch(0.708 0 0);\n}\n\n:root[data-shell-theme=\"dark\"] {\n --sidebar: #13131a;\n --sidebar-foreground: oklch(0.93 0 0);\n --sidebar-primary: oklch(0.93 0 0);\n --sidebar-primary-foreground: #13131a;\n --sidebar-accent: oklch(0.24 0.01 264);\n --sidebar-accent-foreground: oklch(0.95 0 0);\n --sidebar-border: oklch(0.3 0.01 264);\n --sidebar-ring: oklch(0.55 0 0);\n}\n\n.dark {\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.145 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.145 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.985 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.396 0.141 25.723);\n --destructive-foreground: oklch(0.637 0.237 25.331);\n --border: oklch(0.269 0 0);\n --input: oklch(0.269 0 0);\n --ring: oklch(0.439 0 0);\n --font-weight-medium: 500;\n --font-weight-normal: 400;\n --chart-1: oklch(0.488 0.243 264.376);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n --scrollbar-thumb: oklch(0.985 0 0 / 0.22);\n --scrollbar-thumb-hover: oklch(0.985 0 0 / 0.35);\n}\n\n.dark[data-shell-theme=\"light\"] {\n --sidebar: #f5f5f7;\n --sidebar-foreground: #13131a;\n --sidebar-primary: #13131a;\n --sidebar-primary-foreground: #f5f5f7;\n --sidebar-accent: #eceef2;\n --sidebar-accent-foreground: #13131a;\n --sidebar-border: #e0e0e5;\n --sidebar-ring: oklch(0.708 0 0);\n}\n\n.dark[data-shell-theme=\"dark\"] {\n --sidebar: oklch(0.205 0 0);\n --sidebar-foreground: oklch(0.985 0 0);\n --sidebar-primary: oklch(0.488 0.243 264.376);\n --sidebar-primary-foreground: oklch(0.985 0 0);\n --sidebar-accent: oklch(0.269 0 0);\n --sidebar-accent-foreground: oklch(0.985 0 0);\n --sidebar-border: oklch(0.269 0 0);\n --sidebar-ring: oklch(0.439 0 0);\n}\n\n@theme inline {\n --font-sans:\n \"Inter Variable\", \"Inter\", ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-destructive-foreground: var(--destructive-foreground);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-input-background: var(--input-background);\n --color-switch-background: var(--switch-background);\n --color-ring: var(--ring);\n --color-chart-1: var(--chart-1);\n --color-chart-2: var(--chart-2);\n --color-chart-3: var(--chart-3);\n --color-chart-4: var(--chart-4);\n --color-chart-5: var(--chart-5);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --color-sidebar: var(--sidebar);\n --color-sidebar-foreground: var(--sidebar-foreground);\n --color-sidebar-primary: var(--sidebar-primary);\n --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);\n --color-sidebar-accent: var(--sidebar-accent);\n --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);\n --color-sidebar-border: var(--sidebar-border);\n --color-sidebar-ring: var(--sidebar-ring);\n}\n\n@layer base {\n * {\n @apply border-border outline-ring/50;\n }\n\n body {\n @apply bg-background text-foreground font-sans;\n }\n\n /**\n * Default typography styles for HTML elements (h1-h4, p, label, button, input).\n * These are in @layer base, so Tailwind utility classes (like text-sm, text-lg) automatically override them.\n */\n\n html {\n font-size: var(--font-size);\n }\n\n h1 {\n font-size: var(--text-2xl);\n font-weight: var(--font-weight-medium);\n line-height: 1.5;\n }\n\n h2 {\n font-size: var(--text-xl);\n font-weight: var(--font-weight-medium);\n line-height: 1.5;\n }\n\n h3 {\n font-size: var(--text-lg);\n font-weight: var(--font-weight-medium);\n line-height: 1.5;\n }\n\n h4 {\n font-size: var(--text-base);\n font-weight: var(--font-weight-medium);\n line-height: 1.5;\n }\n\n label {\n font-size: var(--text-base);\n font-weight: var(--font-weight-medium);\n line-height: 1.5;\n }\n\n button {\n font-size: var(--text-base);\n font-weight: var(--font-weight-medium);\n line-height: 1.5;\n cursor: pointer;\n }\n\n button:disabled {\n cursor: not-allowed;\n }\n\n input {\n font-size: var(--text-base);\n font-weight: var(--font-weight-normal);\n line-height: 1.5;\n }\n}\n\n@layer components {\n /* Dark shell top bar — remap light page chrome utilities inside title/actions */\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-title\"] .text-foreground,\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-actions\"] .text-foreground {\n color: var(--sidebar-foreground) !important;\n }\n\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-title\"] .text-muted-foreground,\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-actions\"] .text-muted-foreground {\n color: color-mix(in oklch, var(--sidebar-foreground) 62%, transparent) !important;\n }\n\n /* shadcn Button outline/ghost hover utilities use accent tokens (light on dark shell) */\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-actions\"]\n :is([data-slot=\"button\"], [data-shell-top-bar-action]):hover,\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-actions\"]\n :is([data-slot=\"button\"], [data-shell-top-bar-action]):active {\n color: var(--sidebar-foreground) !important;\n }\n\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-actions\"]\n :is([data-slot=\"button\"], [data-shell-top-bar-action]).border-sidebar-border:hover,\n :root[data-shell-theme=\"dark\"] [data-slot=\"shell-top-bar-actions\"]\n :is([data-slot=\"button\"], [data-shell-top-bar-action]).border-sidebar-border:active {\n background-color: color-mix(\n in oklch,\n var(--sidebar-foreground) 12%,\n var(--sidebar-accent)\n ) !important;\n border-color: color-mix(\n in oklch,\n var(--sidebar-foreground) 25%,\n var(--sidebar-border)\n ) !important;\n }\n\n /* Light shell top bar — keep shadcn outline buttons from using page accent hover on shell */\n :root[data-shell-theme=\"light\"] [data-slot=\"shell-top-bar-actions\"]\n :is([data-slot=\"button\"], [data-shell-top-bar-action]).border-sidebar-border:hover,\n :root[data-shell-theme=\"light\"] [data-slot=\"shell-top-bar-actions\"]\n :is([data-slot=\"button\"], [data-shell-top-bar-action]).border-sidebar-border:active {\n background-color: color-mix(\n in oklch,\n var(--sidebar-foreground) 6%,\n var(--sidebar-accent)\n ) !important;\n border-color: color-mix(\n in oklch,\n var(--sidebar-foreground) 14%,\n var(--sidebar-border)\n ) !important;\n color: var(--sidebar-foreground) !important;\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n ),\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto) {\n scrollbar-width: thin;\n scrollbar-color: var(--scrollbar-thumb) transparent;\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )::-webkit-scrollbar,\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )::-webkit-scrollbar-track,\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar-track {\n background: transparent;\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )::-webkit-scrollbar-thumb,\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar-thumb {\n background-color: var(--scrollbar-thumb);\n border-radius: 9999px;\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )::-webkit-scrollbar-thumb:hover,\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n :is(.overflow-y-auto, .overflow-x-auto, .overflow-auto)::-webkit-scrollbar-thumb:hover {\n background-color: var(--scrollbar-thumb-hover);\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n [data-slot=\"scroll-area-thumb\"] {\n background-color: var(--scrollbar-thumb);\n }\n\n :is(\n [data-slot=\"popover-content\"],\n [data-slot=\"hover-card-content\"],\n [data-slot=\"dropdown-menu-content\"],\n [data-slot=\"dropdown-menu-sub-content\"],\n [data-slot=\"select-content\"],\n [data-slot=\"context-menu-content\"],\n [data-slot=\"context-menu-sub-content\"],\n [data-slot=\"menubar-content\"],\n [data-slot=\"menubar-sub-content\"]\n )\n [data-slot=\"scroll-area-thumb\"]:hover {\n background-color: var(--scrollbar-thumb-hover);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/** Green pulse when online; gray dot + last-seen otherwise. Ticks so "3m ago" stays current. */
|
|
4
|
+
declare function SupportPresenceStatus({ lastSeenAt, onlineLabel, neverSeenLabel, className, }: {
|
|
5
|
+
lastSeenAt: string | null;
|
|
6
|
+
onlineLabel?: string;
|
|
7
|
+
neverSeenLabel?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
export { SupportPresenceStatus };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/support/support-presence-status.tsx
|
|
7
|
+
|
|
8
|
+
// src/lib/dateDisplay.ts
|
|
9
|
+
var MS_MIN = 6e4;
|
|
10
|
+
var MS_HOUR = 60 * MS_MIN;
|
|
11
|
+
var MS_DAY = 24 * MS_HOUR;
|
|
12
|
+
function formatRelativeTimeAgo(iso, now = /* @__PURE__ */ new Date()) {
|
|
13
|
+
try {
|
|
14
|
+
const d = new Date(iso.trim());
|
|
15
|
+
if (!Number.isFinite(d.getTime())) return "";
|
|
16
|
+
let diffMs = now.getTime() - d.getTime();
|
|
17
|
+
if (diffMs < 0) diffMs = 0;
|
|
18
|
+
const sec = Math.floor(diffMs / 1e3);
|
|
19
|
+
if (sec < 60) return "just now";
|
|
20
|
+
const min = Math.floor(diffMs / MS_MIN);
|
|
21
|
+
if (min < 60) return `${min}m ago`;
|
|
22
|
+
const hr = Math.floor(diffMs / MS_HOUR);
|
|
23
|
+
if (hr < 24) return `${hr}h ago`;
|
|
24
|
+
const day = Math.floor(diffMs / MS_DAY);
|
|
25
|
+
if (day < 7) return `${day}d ago`;
|
|
26
|
+
const week = Math.floor(day / 7);
|
|
27
|
+
if (week < 5) return `${week}w ago`;
|
|
28
|
+
const mo = Math.floor(day / 30);
|
|
29
|
+
if (mo < 12) return `${mo}mo ago`;
|
|
30
|
+
const yr = Math.floor(day / 365);
|
|
31
|
+
return `${Math.max(1, yr)}y ago`;
|
|
32
|
+
} catch {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function cn(...inputs) {
|
|
37
|
+
return twMerge(clsx(inputs));
|
|
38
|
+
}
|
|
39
|
+
function LiveSpacePulseDot({ className }) {
|
|
40
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("relative flex h-2 w-2 shrink-0", className), "aria-hidden": "true", children: [
|
|
41
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-40" }),
|
|
42
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-emerald-500" })
|
|
43
|
+
] });
|
|
44
|
+
}
|
|
45
|
+
var SUPPORT_PRESENCE_ONLINE_MS = 45e3;
|
|
46
|
+
function supportPresenceFromLastSeen(lastSeenAt, nowMs = Date.now()) {
|
|
47
|
+
if (!lastSeenAt) return { lastSeenAt: null, online: false };
|
|
48
|
+
const ts = new Date(lastSeenAt).getTime();
|
|
49
|
+
if (!Number.isFinite(ts)) return { lastSeenAt: null, online: false };
|
|
50
|
+
return {
|
|
51
|
+
lastSeenAt,
|
|
52
|
+
online: nowMs - ts < SUPPORT_PRESENCE_ONLINE_MS
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function formatSupportPresenceLabel(snapshot, opts) {
|
|
56
|
+
if (snapshot.online) return opts.onlineLabel;
|
|
57
|
+
if (!snapshot.lastSeenAt) return opts.neverSeenLabel;
|
|
58
|
+
const ago = formatRelativeTimeAgo(snapshot.lastSeenAt);
|
|
59
|
+
if (!ago) return opts.neverSeenLabel;
|
|
60
|
+
return ago === "just now" ? "Last seen just now" : `Last seen ${ago}`;
|
|
61
|
+
}
|
|
62
|
+
function OfflineDot({ className }) {
|
|
63
|
+
return /* @__PURE__ */ jsx(
|
|
64
|
+
"span",
|
|
65
|
+
{
|
|
66
|
+
className: cn("inline-flex h-2 w-2 shrink-0 rounded-full bg-muted-foreground/45", className),
|
|
67
|
+
"aria-hidden": "true"
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
function SupportPresenceStatus({
|
|
72
|
+
lastSeenAt,
|
|
73
|
+
onlineLabel = "Online",
|
|
74
|
+
neverSeenLabel = "Offline",
|
|
75
|
+
className
|
|
76
|
+
}) {
|
|
77
|
+
const [, setTick] = useState(0);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
const id = window.setInterval(() => setTick((n) => n + 1), 15e3);
|
|
80
|
+
return () => window.clearInterval(id);
|
|
81
|
+
}, []);
|
|
82
|
+
const snapshot = supportPresenceFromLastSeen(lastSeenAt);
|
|
83
|
+
const label = formatSupportPresenceLabel(snapshot, { onlineLabel, neverSeenLabel });
|
|
84
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex min-w-0 items-center gap-1.5", className), children: [
|
|
85
|
+
snapshot.online ? /* @__PURE__ */ jsx(LiveSpacePulseDot, {}) : /* @__PURE__ */ jsx(OfflineDot, {}),
|
|
86
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: label })
|
|
87
|
+
] });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { SupportPresenceStatus };
|
|
91
|
+
//# sourceMappingURL=support-presence-status.js.map
|
|
92
|
+
//# sourceMappingURL=support-presence-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/dateDisplay.ts","../src/ui/utils.ts","../src/live-space/live-space-pulse-dot.tsx","../src/support/support-presence-status.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"support-presence-status.js","sourcesContent":["/** Parse `HH:mm` wall-clock time. */\nexport function parseWallClockHm(value: string): { h: number; m: number } | undefined {\n const m = /^([01]\\d|2[0-3]):([0-5]\\d)$/.exec(value.trim());\n if (!m) return undefined;\n const h = Number(m[1]);\n const min = Number(m[2]);\n if (h > 23 || min > 59) return undefined;\n return { h, m: min };\n}\n\nexport function toWallClockHmStr(h: number, m: number): string {\n return `${String(h).padStart(2, \"0\")}:${String(m).padStart(2, \"0\")}`;\n}\n\n/** Format stored `HH:mm` without timezone conversion. */\nexport function formatWallClockTime(value: string, timeFormat: \"12h\" | \"24h\"): string {\n const p = parseWallClockHm(value);\n if (!p) return value.trim() || \"—\";\n if (timeFormat === \"24h\") return toWallClockHmStr(p.h, p.m);\n const ap = p.h >= 12 ? \"PM\" : \"AM\";\n const h12 = p.h % 12 || 12;\n return `${h12}:${String(p.m).padStart(2, \"0\")} ${ap}`;\n}\n\n/** Add minutes to a wall-clock `HH:mm`, wrapping at 24h. */\nexport function addWallClockMinutes(value: string, minutes: number): string {\n const p = parseWallClockHm(value);\n if (!p) return value;\n const total = p.h * 60 + p.m + minutes;\n const wrapped = ((total % (24 * 60)) + 24 * 60) % (24 * 60);\n return toWallClockHmStr(Math.floor(wrapped / 60), wrapped % 60);\n}\n\n/** Format `YYYY-MM-DD` as a calendar date (no timezone shift). */\nexport function formatCalendarDate(ymd: string): string {\n if (!ymd || !/^\\d{4}-\\d{2}-\\d{2}$/.test(ymd)) return ymd || \"—\";\n const [y, m, d] = ymd.split(\"-\").map(Number);\n return new Date(y, m - 1, d).toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n\n/** ISO `yyyy-mm-dd` for a local calendar date. */\nexport function toDateStr(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, \"0\");\n const d = String(date.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${d}`;\n}\n\nexport function isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\n/** Short label for a date; shows \"Today\" when it matches the current local day. */\nexport function formatDate(date: Date): string {\n if (isSameDay(date, new Date())) return \"Today\";\n return date.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\nconst MS_MIN = 60_000;\nconst MS_HOUR = 60 * MS_MIN;\nconst MS_DAY = 24 * MS_HOUR;\n\n/**\n * Compact relative time for feeds (e.g. announcements, notifications): `2m ago`, `2d ago`.\n * Uses elapsed wall time from `now` (defaults to current time). Returns \"\" if `iso` is unparseable.\n */\nexport function formatRelativeTimeAgo(iso: string, now: Date = new Date()): string {\n try {\n const d = new Date(iso.trim());\n if (!Number.isFinite(d.getTime())) return \"\";\n let diffMs = now.getTime() - d.getTime();\n if (diffMs < 0) diffMs = 0;\n const sec = Math.floor(diffMs / 1000);\n if (sec < 60) return \"just now\";\n const min = Math.floor(diffMs / MS_MIN);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(diffMs / MS_HOUR);\n if (hr < 24) return `${hr}h ago`;\n const day = Math.floor(diffMs / MS_DAY);\n if (day < 7) return `${day}d ago`;\n const week = Math.floor(day / 7);\n if (week < 5) return `${week}w ago`;\n const mo = Math.floor(day / 30);\n if (mo < 12) return `${mo}mo ago`;\n const yr = Math.floor(day / 365);\n return `${Math.max(1, yr)}y ago`;\n } catch {\n return \"\";\n }\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { cn } from \"../ui/utils\";\n\n/** Ping + solid emerald marker used on Live space page title and sidebar nav. */\nexport function LiveSpacePulseDot({ className }: { className?: string }) {\n return (\n <span className={cn(\"relative flex h-2 w-2 shrink-0\", className)} aria-hidden=\"true\">\n <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-40\" />\n <span className=\"relative inline-flex h-2 w-2 rounded-full bg-emerald-500\" />\n </span>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { formatRelativeTimeAgo } from \"../lib/dateDisplay\";\nimport { LiveSpacePulseDot } from \"../live-space/live-space-pulse-dot\";\nimport { cn } from \"../ui/utils\";\n\nconst SUPPORT_PRESENCE_ONLINE_MS = 45_000;\n\nfunction supportPresenceFromLastSeen(\n lastSeenAt: string | null | undefined,\n nowMs = Date.now(),\n): { lastSeenAt: string | null; online: boolean } {\n if (!lastSeenAt) return { lastSeenAt: null, online: false };\n const ts = new Date(lastSeenAt).getTime();\n if (!Number.isFinite(ts)) return { lastSeenAt: null, online: false };\n return {\n lastSeenAt,\n online: nowMs - ts < SUPPORT_PRESENCE_ONLINE_MS,\n };\n}\n\nfunction formatSupportPresenceLabel(\n snapshot: { online: boolean; lastSeenAt: string | null },\n opts: { onlineLabel: string; neverSeenLabel: string },\n): string {\n if (snapshot.online) return opts.onlineLabel;\n if (!snapshot.lastSeenAt) return opts.neverSeenLabel;\n const ago = formatRelativeTimeAgo(snapshot.lastSeenAt);\n if (!ago) return opts.neverSeenLabel;\n return ago === \"just now\" ? \"Last seen just now\" : `Last seen ${ago}`;\n}\n\nfunction OfflineDot({ className }: { className?: string }) {\n return (\n <span\n className={cn(\"inline-flex h-2 w-2 shrink-0 rounded-full bg-muted-foreground/45\", className)}\n aria-hidden=\"true\"\n />\n );\n}\n\n/** Green pulse when online; gray dot + last-seen otherwise. Ticks so \"3m ago\" stays current. */\nexport function SupportPresenceStatus({\n lastSeenAt,\n onlineLabel = \"Online\",\n neverSeenLabel = \"Offline\",\n className,\n}: {\n lastSeenAt: string | null;\n onlineLabel?: string;\n neverSeenLabel?: string;\n className?: string;\n}) {\n const [, setTick] = useState(0);\n\n useEffect(() => {\n const id = window.setInterval(() => setTick((n) => n + 1), 15_000);\n return () => window.clearInterval(id);\n }, []);\n\n const snapshot = supportPresenceFromLastSeen(lastSeenAt);\n const label = formatSupportPresenceLabel(snapshot, { onlineLabel, neverSeenLabel });\n\n return (\n <span className={cn(\"inline-flex min-w-0 items-center gap-1.5\", className)}>\n {snapshot.online ? <LiveSpacePulseDot /> : <OfflineDot />}\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Monitor, Sun, Moon } from 'lucide-react';
|
|
2
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
7
|
+
import { useTheme } from 'next-themes';
|
|
8
|
+
|
|
9
|
+
// src/theme/theme-appearance-control.tsx
|
|
10
|
+
function cn(...inputs) {
|
|
11
|
+
return twMerge(clsx(inputs));
|
|
12
|
+
}
|
|
13
|
+
function Label({ className, ...props }) {
|
|
14
|
+
return /* @__PURE__ */ jsx(
|
|
15
|
+
LabelPrimitive.Root,
|
|
16
|
+
{
|
|
17
|
+
"data-slot": "label",
|
|
18
|
+
className: cn(
|
|
19
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
20
|
+
className
|
|
21
|
+
),
|
|
22
|
+
...props
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function RadioGroup({
|
|
27
|
+
className,
|
|
28
|
+
...props
|
|
29
|
+
}) {
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
RadioGroupPrimitive.Root,
|
|
32
|
+
{
|
|
33
|
+
"data-slot": "radio-group",
|
|
34
|
+
className: cn("grid gap-3", className),
|
|
35
|
+
...props
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function RadioGroupItem({
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
}) {
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
RadioGroupPrimitive.Item,
|
|
45
|
+
{
|
|
46
|
+
"data-slot": "radio-group-item",
|
|
47
|
+
className: cn(
|
|
48
|
+
"flex size-[18px] shrink-0 items-center justify-center rounded-full border border-border bg-card shadow-sm outline-none transition-[border-color,box-shadow]",
|
|
49
|
+
"focus-visible:border-blue-500 focus-visible:ring-[3px] focus-visible:ring-blue-500/25",
|
|
50
|
+
"aria-invalid:border-red-400 aria-invalid:ring-red-500/20",
|
|
51
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
52
|
+
"data-[state=checked]:border-blue-600",
|
|
53
|
+
className
|
|
54
|
+
),
|
|
55
|
+
...props,
|
|
56
|
+
children: /* @__PURE__ */ jsx(
|
|
57
|
+
RadioGroupPrimitive.Indicator,
|
|
58
|
+
{
|
|
59
|
+
"data-slot": "radio-group-indicator",
|
|
60
|
+
className: "flex items-center justify-center",
|
|
61
|
+
children: /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-blue-600" })
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
var OPTIONS = [
|
|
68
|
+
{
|
|
69
|
+
value: "system",
|
|
70
|
+
label: "System",
|
|
71
|
+
description: "Follow your device appearance",
|
|
72
|
+
icon: Monitor
|
|
73
|
+
},
|
|
74
|
+
{ value: "light", label: "Light (default)", description: "Always use light mode", icon: Sun },
|
|
75
|
+
{ value: "dark", label: "Dark", description: "Always use dark mode", icon: Moon }
|
|
76
|
+
];
|
|
77
|
+
function ThemeAppearanceControl() {
|
|
78
|
+
const { theme, setTheme } = useTheme();
|
|
79
|
+
const value = theme ?? "light";
|
|
80
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
81
|
+
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-foreground", children: "Appearance" }),
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
RadioGroup,
|
|
84
|
+
{
|
|
85
|
+
value,
|
|
86
|
+
onValueChange: (next) => setTheme(next),
|
|
87
|
+
className: "flex flex-col gap-2",
|
|
88
|
+
children: OPTIONS.map((opt) => {
|
|
89
|
+
const Icon = opt.icon;
|
|
90
|
+
return /* @__PURE__ */ jsxs(
|
|
91
|
+
"label",
|
|
92
|
+
{
|
|
93
|
+
htmlFor: `theme-${opt.value}`,
|
|
94
|
+
className: "flex cursor-pointer items-start gap-3 rounded-lg border border-border bg-card px-3 py-2.5 transition-colors has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring/50 hover:bg-accent/50",
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ jsx(RadioGroupItem, { id: `theme-${opt.value}`, value: opt.value, className: "mt-0.5" }),
|
|
97
|
+
/* @__PURE__ */ jsx(Icon, { size: 16, className: "mt-0.5 shrink-0 text-muted-foreground", strokeWidth: 1.75 }),
|
|
98
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: "block text-sm font-medium text-foreground", children: opt.label }),
|
|
100
|
+
/* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground", children: opt.description })
|
|
101
|
+
] })
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
opt.value
|
|
105
|
+
);
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
] });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { ThemeAppearanceControl };
|
|
113
|
+
//# sourceMappingURL=theme-appearance-control.js.map
|
|
114
|
+
//# sourceMappingURL=theme-appearance-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/utils.ts","../src/ui/label.tsx","../src/ui/radio-group.tsx","../src/theme/theme-appearance-control.tsx"],"names":["jsx"],"mappings":"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","file":"theme-appearance-control.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\n\nimport { cn } from \"./utils\";\n\nfunction Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n \"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Label };\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\";\n\nimport { cn } from \"./utils\";\n\nfunction RadioGroup({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n return (\n <RadioGroupPrimitive.Root\n data-slot=\"radio-group\"\n className={cn(\"grid gap-3\", className)}\n {...props}\n />\n );\n}\n\nfunction RadioGroupItem({\n className,\n ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n return (\n <RadioGroupPrimitive.Item\n data-slot=\"radio-group-item\"\n className={cn(\n \"flex size-[18px] shrink-0 items-center justify-center rounded-full border border-border bg-card shadow-sm outline-none transition-[border-color,box-shadow]\",\n \"focus-visible:border-blue-500 focus-visible:ring-[3px] focus-visible:ring-blue-500/25\",\n \"aria-invalid:border-red-400 aria-invalid:ring-red-500/20\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"data-[state=checked]:border-blue-600\",\n className,\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"flex items-center justify-center\"\n >\n <span className=\"size-2.5 rounded-full bg-blue-600\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n );\n}\n\nexport { RadioGroup, RadioGroupItem };\n","import { Monitor, Moon, Sun } from \"lucide-react\";\nimport { Label } from \"../ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"../ui/radio-group\";\nimport { useTheme } from \"./theme-provider\";\nimport type { WebThemeMode } from \"./constants\";\n\nconst OPTIONS: ReadonlyArray<{\n value: WebThemeMode;\n label: string;\n description: string;\n icon: typeof Sun;\n}> = [\n {\n value: \"system\",\n label: \"System\",\n description: \"Follow your device appearance\",\n icon: Monitor,\n },\n { value: \"light\", label: \"Light (default)\", description: \"Always use light mode\", icon: Sun },\n { value: \"dark\", label: \"Dark\", description: \"Always use dark mode\", icon: Moon },\n];\n\nexport function ThemeAppearanceControl() {\n const { theme, setTheme } = useTheme();\n const value = (theme ?? \"light\") as WebThemeMode;\n\n return (\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium text-foreground\">Appearance</Label>\n <RadioGroup\n value={value}\n onValueChange={(next) => setTheme(next as WebThemeMode)}\n className=\"flex flex-col gap-2\"\n >\n {OPTIONS.map((opt) => {\n const Icon = opt.icon;\n return (\n <label\n key={opt.value}\n htmlFor={`theme-${opt.value}`}\n className=\"flex cursor-pointer items-start gap-3 rounded-lg border border-border bg-card px-3 py-2.5 transition-colors has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring/50 hover:bg-accent/50\"\n >\n <RadioGroupItem id={`theme-${opt.value}`} value={opt.value} className=\"mt-0.5\" />\n <Icon size={16} className=\"mt-0.5 shrink-0 text-muted-foreground\" strokeWidth={1.75} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-sm font-medium text-foreground\">{opt.label}</span>\n <span className=\"block text-xs text-muted-foreground\">{opt.description}</span>\n </span>\n </label>\n );\n })}\n </RadioGroup>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/theme/constants.ts
|
|
2
|
+
var WEB_THEME_STORAGE_KEY = "coworking.web.theme";
|
|
3
|
+
|
|
4
|
+
// src/theme/theme-boot-script.ts
|
|
5
|
+
var THEME_BOOT_SCRIPT = `(function(){try{var k=${JSON.stringify(WEB_THEME_STORAGE_KEY)};var t=localStorage.getItem(k)||"light";var d=t==="dark"||(t==="system"&&window.matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.classList.toggle("dark",d);}catch(e){}})();`;
|
|
6
|
+
|
|
7
|
+
export { THEME_BOOT_SCRIPT };
|
|
8
|
+
//# sourceMappingURL=theme-boot-script.js.map
|
|
9
|
+
//# sourceMappingURL=theme-boot-script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/theme/constants.ts","../src/theme/theme-boot-script.ts"],"names":[],"mappings":";AACO,IAAM,qBAAA,GAAwB,qBAAA;;;ACE9B,IAAM,iBAAA,GAAoB,CAAA,sBAAA,EAAyB,IAAA,CAAK,SAAA,CAAU,qBAAqB,CAAC,CAAA,wMAAA","file":"theme-boot-script.js","sourcesContent":["/** localStorage key used by next-themes and the index.html boot script */\nexport const WEB_THEME_STORAGE_KEY = \"coworking.web.theme\";\n\nexport type WebThemeMode = \"system\" | \"light\" | \"dark\";\n","import { WEB_THEME_STORAGE_KEY } from \"./constants\";\n\n/** Inline script for index.html — prevents light flash before React hydrates */\nexport const THEME_BOOT_SCRIPT = `(function(){try{var k=${JSON.stringify(WEB_THEME_STORAGE_KEY)};var t=localStorage.getItem(k)||\"light\";var d=t===\"dark\"||(t===\"system\"&&window.matchMedia(\"(prefers-color-scheme: dark)\").matches);document.documentElement.classList.toggle(\"dark\",d);}catch(e){}})();`;\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
export { useTheme } from 'next-themes';
|
|
4
|
+
|
|
5
|
+
declare function ThemeProvider({ children }: {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}): react_jsx_runtime.JSX.Element;
|
|
8
|
+
|
|
9
|
+
export { ThemeProvider };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ThemeProvider as ThemeProvider$1 } from 'next-themes';
|
|
2
|
+
export { useTheme } from 'next-themes';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/theme/theme-provider.tsx
|
|
6
|
+
|
|
7
|
+
// src/theme/constants.ts
|
|
8
|
+
var WEB_THEME_STORAGE_KEY = "coworking.web.theme";
|
|
9
|
+
function ThemeProvider({ children }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(
|
|
11
|
+
ThemeProvider$1,
|
|
12
|
+
{
|
|
13
|
+
attribute: "class",
|
|
14
|
+
defaultTheme: "light",
|
|
15
|
+
enableSystem: true,
|
|
16
|
+
storageKey: WEB_THEME_STORAGE_KEY,
|
|
17
|
+
disableTransitionOnChange: true,
|
|
18
|
+
children
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { ThemeProvider };
|
|
24
|
+
//# sourceMappingURL=theme-provider.js.map
|
|
25
|
+
//# sourceMappingURL=theme-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/theme/constants.ts","../src/theme/theme-provider.tsx"],"names":["NextThemesProvider"],"mappings":";;;;;;;AACO,IAAM,qBAAA,GAAwB,qBAAA;ACG9B,SAAS,aAAA,CAAc,EAAE,QAAA,EAAS,EAA4B;AACnE,EAAA,uBACE,GAAA;AAAA,IAACA,eAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,OAAA;AAAA,MACV,YAAA,EAAa,OAAA;AAAA,MACb,YAAA,EAAY,IAAA;AAAA,MACZ,UAAA,EAAY,qBAAA;AAAA,MACZ,yBAAA,EAAyB,IAAA;AAAA,MAExB;AAAA;AAAA,GACH;AAEJ","file":"theme-provider.js","sourcesContent":["/** localStorage key used by next-themes and the index.html boot script */\nexport const WEB_THEME_STORAGE_KEY = \"coworking.web.theme\";\n\nexport type WebThemeMode = \"system\" | \"light\" | \"dark\";\n","import { ThemeProvider as NextThemesProvider } from \"next-themes\";\nimport type { ReactNode } from \"react\";\nimport { WEB_THEME_STORAGE_KEY } from \"./constants\";\n\nexport function ThemeProvider({ children }: { children: ReactNode }) {\n return (\n <NextThemesProvider\n attribute=\"class\"\n defaultTheme=\"light\"\n enableSystem\n storageKey={WEB_THEME_STORAGE_KEY}\n disableTransitionOnChange\n >\n {children}\n </NextThemesProvider>\n );\n}\n\nexport { useTheme } from \"next-themes\";\n"]}
|