@open-webapp/calendar 0.4.0 → 0.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.
- package/README.md +30 -2
- package/dist/react/CalendarPane.d.ts +1 -0
- package/dist/react/CalendarPane.js +5 -5
- package/dist/react/CalendarSelector.d.ts +4 -2
- package/dist/react/CalendarSelector.js +4 -4
- package/dist/styles.css +198 -187
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ void controller.refresh(); // then syncs from Google
|
|
|
38
38
|
<CalendarPane
|
|
39
39
|
sources={sources}
|
|
40
40
|
controller={controller}
|
|
41
|
+
theme="system" // optional: 'system' | 'light' | 'dark'
|
|
41
42
|
selectedRsvpStatuses={statuses} // Set<RsvpStatus>
|
|
42
43
|
onRsvpStatusesChange={setStatuses}
|
|
43
44
|
connected={connected} // optional, see CalendarPane props
|
|
@@ -146,6 +147,7 @@ Call at top level of a vitest file; it registers a `describe('StorageAdapter con
|
|
|
146
147
|
| --- | --- | --- |
|
|
147
148
|
| `sources` | `Source[]` | shown accounts; 2+ enables multi-source UI (per-source color and email) |
|
|
148
149
|
| `controller` | `CalendarController` | |
|
|
150
|
+
| `theme?` | `'system' \| 'light' \| 'dark'` | defaults to `'system'`, including when `undefined`; applies to every pane state and all internal selectors |
|
|
149
151
|
| `selectedRsvpStatuses` | `Set<RsvpStatus>` | filter; `DEFAULT_RSVP_STATUSES` = accepted, tentative, needsAction |
|
|
150
152
|
| `onRsvpStatusesChange` | `(next) => void` | |
|
|
151
153
|
| `renderEventAction?` | `(event) => ReactNode` | per-event slot |
|
|
@@ -180,13 +182,34 @@ One footer combobox opens a shared searchable dropdown, with calendars grouped u
|
|
|
180
182
|
|
|
181
183
|
### CalendarSelector props
|
|
182
184
|
|
|
183
|
-
`calendars: CalendarInfo[]`, `selectedIds: string[]`, `onChange(ids)`, `heading?: string` (account heading in multi-source use). It has no slot props or `popupName`. At least one calendar stays selected (deselecting the last one is ignored). "Clear" resets to the primary calendar. Built-in copy: "Search calendars", "Select all", "Clear", "Done", "No calendars found", "No calendars available".
|
|
185
|
+
`calendars: CalendarInfo[]`, `selectedIds: string[]`, `onChange(ids)`, `heading?: string` (account heading in multi-source use), `theme?: 'system' | 'light' | 'dark'` (defaults to `'system'`, including when `undefined`). It has no slot props or `popupName`. At least one calendar stays selected (deselecting the last one is ignored). "Clear" resets to the primary calendar. Built-in copy: "Search calendars", "Select all", "Clear", "Done", "No calendars found", "No calendars available".
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import { CalendarSelector } from '@open-webapp/calendar';
|
|
189
|
+
import '@open-webapp/calendar/styles.css';
|
|
190
|
+
|
|
191
|
+
<CalendarSelector
|
|
192
|
+
calendars={calendars}
|
|
193
|
+
selectedIds={selectedIds}
|
|
194
|
+
onChange={setSelectedIds}
|
|
195
|
+
heading="me@example.com"
|
|
196
|
+
theme="dark"
|
|
197
|
+
/>;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Theme behavior
|
|
201
|
+
|
|
202
|
+
Both components follow the OS/browser `prefers-color-scheme` preference live in `'system'` mode; omitting `theme` preserves this default. Explicit `'light'` and `'dark'` ignore OS changes. Hosts can change the prop on a mounted component (including back to `'system'` or `undefined`) without remounting, closing an open dropdown, losing its search query, focus or keyboard-active option, changing selected calendars, or resetting the pane's saved RSVP selection. Theme changes do not trigger selection callbacks or controller refreshes.
|
|
203
|
+
|
|
204
|
+
Each pane forwards its requested mode to its unified grouped footer selector, including both account groups, account-local actions and the shared search. The existing single-trigger layout and cross-account keyboard navigation are preserved. Standalone selectors choose their own mode: an omitted/system selector follows the OS even inside an explicitly dark or light pane. Adjacent and nested instances can use opposite modes independently; no document/body theme switch is applied.
|
|
205
|
+
|
|
206
|
+
The host owns theme-picker UI and preference persistence (for example, saving a choice and passing it back as `theme`). The package neither stores the choice nor adds it to the controller. Hosts also own styling of `emptyState`, `sourceNotice` and `renderEventAction` slot content; give custom content explicit styles where needed rather than relying on the built-in palette.
|
|
184
207
|
|
|
185
208
|
The exported standalone selector keeps its single-list props and behavior; Select all adds only search matches while retaining existing selections.
|
|
186
209
|
|
|
187
210
|
### Host CSS
|
|
188
211
|
|
|
189
|
-
`styles.css` is self-contained
|
|
212
|
+
`styles.css` is self-contained, using component-scoped semantic palette tokens and native-control `color-scheme`. Each pane/selector root resets the full palette; explicit dark overrides and system-only `prefers-color-scheme` rules keep instances isolated. It requires no host CSS variables. Layout/status variables:
|
|
190
213
|
|
|
191
214
|
- `--calendar-footer-height` (default `64px`, set on `.calendar-pane`; override to match host footer)
|
|
192
215
|
- `--chip-row-height` (fallback `44px`; host may set it to match its chip row for sticky headers)
|
|
@@ -194,6 +217,11 @@ The exported standalone selector keeps its single-list props and behavior; Selec
|
|
|
194
217
|
|
|
195
218
|
The Unaccepted count badge uses `.calendar-rsvp-chip-badge`, with light and dark styling included in `styles.css`.
|
|
196
219
|
|
|
220
|
+
## 0.5.0 (minor, additive)
|
|
221
|
+
|
|
222
|
+
- Adds optional `theme?: 'system' | 'light' | 'dark'` to both React components, with live OS tracking by default and live per-instance overrides.
|
|
223
|
+
- Themes all built-in pane states and internal/standalone selectors while preserving existing palettes, layout, copy and interaction contracts. Existing callers need no migration.
|
|
224
|
+
|
|
197
225
|
## 0.4.0 (BREAKING pre-1.0 minor)
|
|
198
226
|
|
|
199
227
|
- CalendarPane replaces per-account footer triggers with one shared dropdown grouped by account. Hosts relying on multiple footer triggers must adapt. Account-local selection rules and the exported standalone CalendarSelector remain compatible.
|
|
@@ -3,6 +3,7 @@ import type { CalendarEvent, RsvpStatus, Source } from '../core/types.js';
|
|
|
3
3
|
import type { CalendarController } from '../core/controller.js';
|
|
4
4
|
export type RsvpSelection = Set<RsvpStatus>;
|
|
5
5
|
export interface CalendarPaneProps {
|
|
6
|
+
theme?: 'system' | 'light' | 'dark';
|
|
6
7
|
sources: Source[];
|
|
7
8
|
controller: CalendarController;
|
|
8
9
|
selectedRsvpStatuses: RsvpSelection;
|
|
@@ -100,7 +100,7 @@ function usableUrl(url) {
|
|
|
100
100
|
}
|
|
101
101
|
export function CalendarPane(props) {
|
|
102
102
|
const isDesktop = useWindowWidth() >= 960;
|
|
103
|
-
const { sources, controller, selectedRsvpStatuses } = props;
|
|
103
|
+
const { sources, controller, selectedRsvpStatuses, theme = 'system' } = props;
|
|
104
104
|
const popupName = props.popupName ?? DEFAULT_POPUP_NAME;
|
|
105
105
|
const [version, setVersion] = useState(0);
|
|
106
106
|
useEffect(() => {
|
|
@@ -286,10 +286,10 @@ export function CalendarPane(props) {
|
|
|
286
286
|
return () => observer.disconnect();
|
|
287
287
|
}, [connected, needsReauth]);
|
|
288
288
|
if (!connected) {
|
|
289
|
-
return (_jsx("div", { className: "calendar-pane", children: _jsx("div", { className: "calendar-pane-prompt", children: props.emptyState ?? (_jsxs(_Fragment, { children: [_jsx("p", { children: "Not connected to Google Calendar." }), _jsx("button", { className: "calendar-connect-button", onClick: props.onConnect, children: "Connect Google Calendar" })] })) }) }));
|
|
289
|
+
return (_jsx("div", { className: "calendar-pane", "data-calendar-theme": theme, children: _jsx("div", { className: "calendar-pane-prompt", children: props.emptyState ?? (_jsxs(_Fragment, { children: [_jsx("p", { children: "Not connected to Google Calendar." }), _jsx("button", { className: "calendar-connect-button", onClick: props.onConnect, children: "Connect Google Calendar" })] })) }) }));
|
|
290
290
|
}
|
|
291
291
|
if (needsReauth) {
|
|
292
|
-
return (_jsx("div", { className: "calendar-pane", children: _jsx("div", { className: "calendar-pane-prompt", children: props.sourceNotice && needsScopeSources.length > 0 ? (needsScopeSources.map((s) => _jsx("div", { children: props.sourceNotice?.(s) }, s.id))) : (_jsxs(_Fragment, { children: [_jsx("p", { children: "Calendar connection needs reauthorization." }), _jsx("button", { className: "calendar-connect-button", onClick: props.onReconnect, children: "Reconnect to restore sync" })] })) }) }));
|
|
292
|
+
return (_jsx("div", { className: "calendar-pane", "data-calendar-theme": theme, children: _jsx("div", { className: "calendar-pane-prompt", children: props.sourceNotice && needsScopeSources.length > 0 ? (needsScopeSources.map((s) => _jsx("div", { children: props.sourceNotice?.(s) }, s.id))) : (_jsxs(_Fragment, { children: [_jsx("p", { children: "Calendar connection needs reauthorization." }), _jsx("button", { className: "calendar-connect-button", onClick: props.onReconnect, children: "Reconnect to restore sync" })] })) }) }));
|
|
293
293
|
}
|
|
294
294
|
const sourcesWithEvents = new Set(filteredEvents.map((e) => e.sourceId));
|
|
295
295
|
const hasErrorWithoutEvents = sources.some((s) => statuses[s.id] === 'error' && !sourcesWithEvents.has(s.id));
|
|
@@ -298,7 +298,7 @@ export function CalendarPane(props) {
|
|
|
298
298
|
const loading = ctrlState.loading && filteredEvents.length === 0;
|
|
299
299
|
const emptyStateText = 'No matching events in the next 30 days';
|
|
300
300
|
const showCalendarSelector = calendarSources.length > 0;
|
|
301
|
-
return (_jsxs("div", { className: "calendar-pane", ref: paneRef, children: [_jsxs("div", { className: "calendar-pane-scroll", children: [_jsxs("div", { className: "calendar-rsvp-chips", ref: chipsRef, children: [_jsx("button", { type: "button", className: "calendar-rsvp-chip calendar-scroll-today-btn", "aria-label": "Scroll to today", title: "Scroll to today", onClick: () => recenter('smooth'), children: _jsxs("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [_jsx("rect", { x: "2", y: "3", width: "11", height: "10", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }), _jsx("path", { d: "M2 6H13", stroke: "currentColor", strokeWidth: "1.2" }), _jsx("path", { d: "M5 2V4M10 2V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }), _jsx("circle", { cx: "7.5", cy: "9.5", r: "1.3", fill: "currentColor" })] }) }), RSVP_CHIPS.map((chip) => (_jsxs("button", { type: "button", className: `calendar-rsvp-chip${(chip.status === 'needsAction' ? isExclusive : selectedRsvpStatuses.has(chip.status)) ? ' selected' : ''}`, "aria-pressed": chip.status === 'needsAction' ? isExclusive : selectedRsvpStatuses.has(chip.status), "aria-label": chip.status === 'needsAction' ? `${chip.label} (${unacceptedCount})` : chip.label, title: chip.status === 'needsAction' ? `${chip.label} (${unacceptedCount})` : chip.label, onClick: () => chip.status === 'needsAction' ? handleUnaccepted() : handleToggle(chip.status), children: [chip.icon, chip.status === 'needsAction' && (_jsx("span", { className: "calendar-rsvp-chip-badge", "aria-hidden": "true", children: unacceptedCount > 99 ? '99+' : unacceptedCount }))] }, chip.status)))] }), needsScopeSources.map((s) => (_jsx("div", { children: props.sourceNotice?.(s) }, s.id))), error && (_jsx("div", { className: "empty-state calendar-empty-state", role: "alert", children: _jsx("p", { children: "Couldn't load calendar events. Try again shortly." }) })), !(error && filteredEvents.length === 0) && (_jsxs("div", { className: "calendar-day-groups", children: [dayGroups.map((group) => (_jsxs("div", { className: "calendar-day-group", children: [_jsx("div", { className: "calendar-day-header", ref: (el) => {
|
|
301
|
+
return (_jsxs("div", { className: "calendar-pane", "data-calendar-theme": theme, ref: paneRef, children: [_jsxs("div", { className: "calendar-pane-scroll", children: [_jsxs("div", { className: "calendar-rsvp-chips", ref: chipsRef, children: [_jsx("button", { type: "button", className: "calendar-rsvp-chip calendar-scroll-today-btn", "aria-label": "Scroll to today", title: "Scroll to today", onClick: () => recenter('smooth'), children: _jsxs("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [_jsx("rect", { x: "2", y: "3", width: "11", height: "10", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }), _jsx("path", { d: "M2 6H13", stroke: "currentColor", strokeWidth: "1.2" }), _jsx("path", { d: "M5 2V4M10 2V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }), _jsx("circle", { cx: "7.5", cy: "9.5", r: "1.3", fill: "currentColor" })] }) }), RSVP_CHIPS.map((chip) => (_jsxs("button", { type: "button", className: `calendar-rsvp-chip${(chip.status === 'needsAction' ? isExclusive : selectedRsvpStatuses.has(chip.status)) ? ' selected' : ''}`, "aria-pressed": chip.status === 'needsAction' ? isExclusive : selectedRsvpStatuses.has(chip.status), "aria-label": chip.status === 'needsAction' ? `${chip.label} (${unacceptedCount})` : chip.label, title: chip.status === 'needsAction' ? `${chip.label} (${unacceptedCount})` : chip.label, onClick: () => chip.status === 'needsAction' ? handleUnaccepted() : handleToggle(chip.status), children: [chip.icon, chip.status === 'needsAction' && (_jsx("span", { className: "calendar-rsvp-chip-badge", "aria-hidden": "true", children: unacceptedCount > 99 ? '99+' : unacceptedCount }))] }, chip.status)))] }), needsScopeSources.map((s) => (_jsx("div", { children: props.sourceNotice?.(s) }, s.id))), error && (_jsx("div", { className: "empty-state calendar-empty-state", role: "alert", children: _jsx("p", { children: "Couldn't load calendar events. Try again shortly." }) })), !(error && filteredEvents.length === 0) && (_jsxs("div", { className: "calendar-day-groups", children: [dayGroups.map((group) => (_jsxs("div", { className: "calendar-day-group", children: [_jsx("div", { className: "calendar-day-header", ref: (el) => {
|
|
302
302
|
if (el) {
|
|
303
303
|
dayHeaderRefs.current.set(group.dateKey, el);
|
|
304
304
|
}
|
|
@@ -343,7 +343,7 @@ export function CalendarPane(props) {
|
|
|
343
343
|
openEventPopup(event.htmlLink, popupRef, popupName);
|
|
344
344
|
}
|
|
345
345
|
}, children: _jsx("span", { className: "calendar-event-title", children: event.summary }) })) : (_jsx("span", { className: "calendar-event-title", children: event.summary })), props.renderEventAction?.(event)] }), showCalendarLabel && (_jsxs("span", { className: "calendar-event-calendar", children: [_jsx("span", { className: "calendar-event-calendar-dot", style: { backgroundColor: calendar.backgroundColor } }), calendar.summary] })), showOrganizerLabel && (_jsxs("span", { className: "calendar-event-organizer", children: [multi && (_jsx("span", { className: "calendar-event-source-dot", style: { backgroundColor: sourceColor(event.sourceId) } })), organizerText] }))] }, eventKey));
|
|
346
|
-
})] }, group.dateKey))), loading && _jsx("p", { className: "calendar-empty-state-text", children: "Loading calendar\u2026" }), filteredEvents.length === 0 && !loading && !error && needsScopeSources.length === 0 && _jsx("p", { className: "calendar-empty-state-text", children: emptyStateText })] }))] }), showCalendarSelector && (_jsx("footer", { className: "calendar-pane-footer", children: _jsx(GroupedCalendarSelector, { groups: calendarSources.map((s) => ({
|
|
346
|
+
})] }, group.dateKey))), loading && _jsx("p", { className: "calendar-empty-state-text", children: "Loading calendar\u2026" }), filteredEvents.length === 0 && !loading && !error && needsScopeSources.length === 0 && _jsx("p", { className: "calendar-empty-state-text", children: emptyStateText })] }))] }), showCalendarSelector && (_jsx("footer", { className: "calendar-pane-footer", children: _jsx(GroupedCalendarSelector, { theme: theme, groups: calendarSources.map((s) => ({
|
|
347
347
|
id: s.id,
|
|
348
348
|
calendars: controller.getCalendars(s.id),
|
|
349
349
|
selectedIds: controller.getSelectedIds(s.id),
|
|
@@ -5,12 +5,14 @@ interface CalendarSelectorProps {
|
|
|
5
5
|
onChange: (selectedIds: string[]) => void;
|
|
6
6
|
/** Optional account heading (used when several sources are shown). */
|
|
7
7
|
heading?: string;
|
|
8
|
+
theme?: 'system' | 'light' | 'dark';
|
|
8
9
|
}
|
|
9
|
-
export declare function CalendarSelector({ calendars, selectedIds, onChange, heading }: CalendarSelectorProps): import("react").JSX.Element;
|
|
10
|
+
export declare function CalendarSelector({ calendars, selectedIds, onChange, heading, theme }: CalendarSelectorProps): import("react").JSX.Element;
|
|
10
11
|
/** Internal pane renderer; intentionally not re-exported from the package barrel. */
|
|
11
|
-
export declare function GroupedCalendarSelector({ groups }: {
|
|
12
|
+
export declare function GroupedCalendarSelector({ groups, theme }: {
|
|
12
13
|
groups: (CalendarSelectorProps & {
|
|
13
14
|
id: string;
|
|
14
15
|
})[];
|
|
16
|
+
theme?: CalendarSelectorProps['theme'];
|
|
15
17
|
}): import("react").JSX.Element;
|
|
16
18
|
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useId, useRef, useState } from 'react';
|
|
3
3
|
import { filterCalendarsByName, summarizeCalendarSelection } from '../core/events.js';
|
|
4
|
-
export function CalendarSelector({ calendars, selectedIds, onChange, heading }) {
|
|
5
|
-
return _jsx(GroupedCalendarSelector, { groups: [{ id: '', calendars, selectedIds, onChange, heading }] });
|
|
4
|
+
export function CalendarSelector({ calendars, selectedIds, onChange, heading, theme = 'system' }) {
|
|
5
|
+
return _jsx(GroupedCalendarSelector, { theme: theme, groups: [{ id: '', calendars, selectedIds, onChange, heading }] });
|
|
6
6
|
}
|
|
7
7
|
/** Internal pane renderer; intentionally not re-exported from the package barrel. */
|
|
8
|
-
export function GroupedCalendarSelector({ groups }) {
|
|
8
|
+
export function GroupedCalendarSelector({ groups, theme = 'system' }) {
|
|
9
9
|
const [open, setOpen] = useState(false);
|
|
10
10
|
const [query, setQuery] = useState('');
|
|
11
11
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
@@ -90,7 +90,7 @@ export function GroupedCalendarSelector({ groups }) {
|
|
|
90
90
|
? summarizeCalendarSelection(groups[0].selectedIds, groups[0].calendars)
|
|
91
91
|
: `${groups.reduce((count, group) => count + group.selectedIds.length, 0)} calendars selected`;
|
|
92
92
|
const activeCalendar = visibleCalendars[activeIndex];
|
|
93
|
-
return (_jsxs("div", { className: "calendar-selector", ref: rootRef, children: [_jsx("button", { ref: buttonRef, type: "button", role: "combobox", "aria-label": label, "aria-expanded": open, "aria-controls": listboxId, "aria-haspopup": "listbox", onClick: () => {
|
|
93
|
+
return (_jsxs("div", { className: "calendar-selector", "data-calendar-theme": theme, ref: rootRef, children: [_jsx("button", { ref: buttonRef, type: "button", role: "combobox", "aria-label": label, "aria-expanded": open, "aria-controls": listboxId, "aria-haspopup": "listbox", onClick: () => {
|
|
94
94
|
setOpen((isOpen) => !isOpen);
|
|
95
95
|
setQuery('');
|
|
96
96
|
setActiveIndex(0);
|
package/dist/styles.css
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
.calendar-pane,
|
|
2
|
+
.calendar-selector {
|
|
3
|
+
/* Reset the complete palette at every independent component boundary. */
|
|
4
|
+
--calendar-scheme: light;
|
|
5
|
+
--calendar-surface: #ffffff;
|
|
6
|
+
--calendar-text: #222;
|
|
7
|
+
--calendar-border: #eee;
|
|
8
|
+
--calendar-prompt: #555;
|
|
9
|
+
--calendar-accent: #00a9ce;
|
|
10
|
+
--calendar-hover: #f0f8fb;
|
|
11
|
+
--calendar-chip-text: #333;
|
|
12
|
+
--calendar-chip-border: #ccc;
|
|
13
|
+
--calendar-chip-selected: #081a59;
|
|
14
|
+
--calendar-chip-selected-text: #ffffff;
|
|
15
|
+
--calendar-badge: #e8eefb;
|
|
16
|
+
--calendar-badge-text: #081a59;
|
|
17
|
+
--calendar-header: #f5f5f5;
|
|
18
|
+
--calendar-allday: #fdf6e3;
|
|
19
|
+
--calendar-highlight: #f0f8fb;
|
|
20
|
+
--calendar-insert: #888;
|
|
21
|
+
--calendar-insert-hover: #222;
|
|
22
|
+
--calendar-insert-background: rgba(0, 0, 0, 0.06);
|
|
23
|
+
--calendar-focus: #1a73e8;
|
|
24
|
+
--calendar-rsvp-accepted: #2e7d32;
|
|
25
|
+
--calendar-rsvp-tentative: #d97706;
|
|
26
|
+
--calendar-rsvp-needsAction: #2563eb;
|
|
27
|
+
--calendar-rsvp-declined: #dc2626;
|
|
28
|
+
--calendar-selector-border: #ccc;
|
|
29
|
+
--calendar-selector-text: #1a1a1a;
|
|
30
|
+
--calendar-selector-shadow: 0 4px 14px rgb(0 0 0 / 15%);
|
|
31
|
+
--calendar-control-border: #767676;
|
|
32
|
+
--calendar-control-background: #efefef;
|
|
33
|
+
--calendar-input-background: #ffffff;
|
|
34
|
+
--calendar-control-text: #000000;
|
|
35
|
+
--calendar-control-width: 2px;
|
|
36
|
+
--calendar-button-border-style: outset;
|
|
37
|
+
--calendar-input-border-style: inset;
|
|
38
|
+
--calendar-option-hover: transparent;
|
|
39
|
+
--calendar-option-active: #e8f5f8;
|
|
40
|
+
--calendar-muted: #888;
|
|
41
|
+
--calendar-time: #666;
|
|
42
|
+
--calendar-empty: #999;
|
|
43
|
+
--calendar-chip-hover: #00a9ce;
|
|
44
|
+
--calendar-checkbox: #22a6c0;
|
|
45
|
+
color-scheme: var(--calendar-scheme);
|
|
46
|
+
color: var(--calendar-text);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.calendar-pane {
|
|
50
|
+
background: var(--calendar-surface);
|
|
51
|
+
}
|
|
52
|
+
|
|
1
53
|
.calendar-pane {
|
|
2
54
|
--calendar-footer-height: 64px;
|
|
3
55
|
display: flex;
|
|
@@ -23,8 +75,8 @@
|
|
|
23
75
|
box-sizing: border-box;
|
|
24
76
|
min-height: var(--calendar-footer-height);
|
|
25
77
|
padding: 12px 16px;
|
|
26
|
-
border-top: 1px solid
|
|
27
|
-
background:
|
|
78
|
+
border-top: 1px solid var(--calendar-border);
|
|
79
|
+
background: var(--calendar-surface);
|
|
28
80
|
}
|
|
29
81
|
|
|
30
82
|
.calendar-pane-prompt {
|
|
@@ -37,7 +89,7 @@
|
|
|
37
89
|
|
|
38
90
|
.calendar-pane-prompt p {
|
|
39
91
|
margin: 0;
|
|
40
|
-
color:
|
|
92
|
+
color: var(--calendar-prompt);
|
|
41
93
|
font-size: 14px;
|
|
42
94
|
}
|
|
43
95
|
|
|
@@ -45,15 +97,15 @@
|
|
|
45
97
|
padding: 10px 16px;
|
|
46
98
|
font-size: 14px;
|
|
47
99
|
font-weight: 500;
|
|
48
|
-
background:
|
|
49
|
-
color:
|
|
50
|
-
border: 1px solid
|
|
100
|
+
background: var(--calendar-surface);
|
|
101
|
+
color: var(--calendar-accent);
|
|
102
|
+
border: 1px solid var(--calendar-accent);
|
|
51
103
|
border-radius: 6px;
|
|
52
104
|
cursor: pointer;
|
|
53
105
|
}
|
|
54
106
|
|
|
55
107
|
.calendar-connect-button:hover {
|
|
56
|
-
background:
|
|
108
|
+
background: var(--calendar-hover);
|
|
57
109
|
}
|
|
58
110
|
|
|
59
111
|
.calendar-rsvp-chips {
|
|
@@ -63,7 +115,7 @@
|
|
|
63
115
|
flex-wrap: wrap;
|
|
64
116
|
position: sticky;
|
|
65
117
|
top: 0;
|
|
66
|
-
background:
|
|
118
|
+
background: var(--calendar-surface);
|
|
67
119
|
z-index: 2;
|
|
68
120
|
}
|
|
69
121
|
|
|
@@ -79,8 +131,8 @@
|
|
|
79
131
|
gap: 4px;
|
|
80
132
|
padding: 0 8px;
|
|
81
133
|
background: transparent;
|
|
82
|
-
color:
|
|
83
|
-
border: 1px solid
|
|
134
|
+
color: var(--calendar-chip-text);
|
|
135
|
+
border: 1px solid var(--calendar-chip-border);
|
|
84
136
|
border-radius: 999px;
|
|
85
137
|
cursor: pointer;
|
|
86
138
|
}
|
|
@@ -88,25 +140,25 @@
|
|
|
88
140
|
.calendar-scroll-today-btn {
|
|
89
141
|
margin-right: 4px;
|
|
90
142
|
padding-right: 4px;
|
|
91
|
-
border-right: 1px solid
|
|
143
|
+
border-right: 1px solid var(--calendar-chip-border);
|
|
92
144
|
}
|
|
93
145
|
|
|
94
146
|
.calendar-rsvp-chip:hover {
|
|
95
|
-
border-color:
|
|
147
|
+
border-color: var(--calendar-chip-hover);
|
|
96
148
|
}
|
|
97
149
|
|
|
98
150
|
.calendar-rsvp-chip.selected {
|
|
99
|
-
background:
|
|
100
|
-
color:
|
|
101
|
-
border-color:
|
|
151
|
+
background: var(--calendar-chip-selected);
|
|
152
|
+
color: var(--calendar-chip-selected-text);
|
|
153
|
+
border-color: var(--calendar-chip-selected);
|
|
102
154
|
}
|
|
103
155
|
|
|
104
156
|
.calendar-rsvp-chip-badge {
|
|
105
157
|
min-width: 16px;
|
|
106
158
|
padding: 1px 4px;
|
|
107
159
|
border-radius: 999px;
|
|
108
|
-
background:
|
|
109
|
-
color:
|
|
160
|
+
background: var(--calendar-badge);
|
|
161
|
+
color: var(--calendar-badge-text);
|
|
110
162
|
font-size: 11px;
|
|
111
163
|
font-weight: 600;
|
|
112
164
|
line-height: 16px;
|
|
@@ -116,7 +168,7 @@
|
|
|
116
168
|
|
|
117
169
|
.calendar-empty-state {
|
|
118
170
|
padding: 24px 16px;
|
|
119
|
-
color:
|
|
171
|
+
color: var(--calendar-empty);
|
|
120
172
|
font-size: 14px;
|
|
121
173
|
}
|
|
122
174
|
|
|
@@ -133,8 +185,8 @@
|
|
|
133
185
|
.calendar-day-header {
|
|
134
186
|
position: sticky;
|
|
135
187
|
top: var(--chip-row-height, 44px);
|
|
136
|
-
background:
|
|
137
|
-
color:
|
|
188
|
+
background: var(--calendar-header);
|
|
189
|
+
color: var(--calendar-chip-text);
|
|
138
190
|
font-size: 13px;
|
|
139
191
|
font-weight: 600;
|
|
140
192
|
padding: 8px 16px;
|
|
@@ -147,7 +199,7 @@
|
|
|
147
199
|
gap: 8px;
|
|
148
200
|
padding: 10px 16px;
|
|
149
201
|
border-left: 3px solid var(--rsvp-bar, transparent);
|
|
150
|
-
border-bottom: 1px solid
|
|
202
|
+
border-bottom: 1px solid var(--calendar-border);
|
|
151
203
|
}
|
|
152
204
|
|
|
153
205
|
.calendar-event-row {
|
|
@@ -156,28 +208,28 @@
|
|
|
156
208
|
gap: 8px;
|
|
157
209
|
padding: 10px 16px;
|
|
158
210
|
border-left: 3px solid var(--rsvp-bar, transparent);
|
|
159
|
-
border-bottom: 1px solid
|
|
211
|
+
border-bottom: 1px solid var(--calendar-border);
|
|
160
212
|
}
|
|
161
213
|
|
|
162
214
|
.calendar-event-allday {
|
|
163
|
-
background:
|
|
215
|
+
background: var(--calendar-allday);
|
|
164
216
|
font-style: italic;
|
|
165
217
|
}
|
|
166
218
|
|
|
167
219
|
.calendar-event-row--rsvp-accepted {
|
|
168
|
-
--rsvp-bar:
|
|
220
|
+
--rsvp-bar: var(--calendar-rsvp-accepted);
|
|
169
221
|
}
|
|
170
222
|
|
|
171
223
|
.calendar-event-row--rsvp-tentative {
|
|
172
|
-
--rsvp-bar:
|
|
224
|
+
--rsvp-bar: var(--calendar-rsvp-tentative);
|
|
173
225
|
}
|
|
174
226
|
|
|
175
227
|
.calendar-event-row--rsvp-needsAction {
|
|
176
|
-
--rsvp-bar:
|
|
228
|
+
--rsvp-bar: var(--calendar-rsvp-needsAction);
|
|
177
229
|
}
|
|
178
230
|
|
|
179
231
|
.calendar-event-row--rsvp-declined {
|
|
180
|
-
--rsvp-bar:
|
|
232
|
+
--rsvp-bar: var(--calendar-rsvp-declined);
|
|
181
233
|
}
|
|
182
234
|
|
|
183
235
|
.calendar-event-header {
|
|
@@ -217,36 +269,36 @@
|
|
|
217
269
|
border: none;
|
|
218
270
|
border-radius: 4px;
|
|
219
271
|
background: transparent;
|
|
220
|
-
color:
|
|
272
|
+
color: var(--calendar-insert);
|
|
221
273
|
cursor: pointer;
|
|
222
274
|
}
|
|
223
275
|
|
|
224
276
|
.calendar-event-insert-link:hover {
|
|
225
|
-
color:
|
|
226
|
-
background:
|
|
277
|
+
color: var(--calendar-insert-hover);
|
|
278
|
+
background: var(--calendar-insert-background);
|
|
227
279
|
}
|
|
228
280
|
|
|
229
281
|
.calendar-event-insert-link:focus-visible {
|
|
230
|
-
outline: 2px solid
|
|
282
|
+
outline: 2px solid var(--calendar-focus);
|
|
231
283
|
outline-offset: 1px;
|
|
232
|
-
color:
|
|
284
|
+
color: var(--calendar-insert-hover);
|
|
233
285
|
}
|
|
234
286
|
|
|
235
287
|
.calendar-event-time {
|
|
236
288
|
font-size: 12px;
|
|
237
|
-
color:
|
|
289
|
+
color: var(--calendar-time);
|
|
238
290
|
min-width: 110px;
|
|
239
291
|
flex-shrink: 0;
|
|
240
292
|
}
|
|
241
293
|
|
|
242
294
|
.calendar-event-title {
|
|
243
295
|
font-size: 14px;
|
|
244
|
-
color:
|
|
296
|
+
color: var(--calendar-text);
|
|
245
297
|
}
|
|
246
298
|
|
|
247
299
|
.calendar-event-organizer {
|
|
248
300
|
font-size: 12px;
|
|
249
|
-
color:
|
|
301
|
+
color: var(--calendar-muted);
|
|
250
302
|
}
|
|
251
303
|
|
|
252
304
|
.calendar-event-calendar {
|
|
@@ -254,7 +306,7 @@
|
|
|
254
306
|
align-items: center;
|
|
255
307
|
gap: 5px;
|
|
256
308
|
font-size: 12px;
|
|
257
|
-
color:
|
|
309
|
+
color: var(--calendar-muted);
|
|
258
310
|
}
|
|
259
311
|
|
|
260
312
|
.calendar-event-calendar-dot {
|
|
@@ -267,130 +319,104 @@
|
|
|
267
319
|
.calendar-event-join {
|
|
268
320
|
font-size: 12px;
|
|
269
321
|
font-weight: 500;
|
|
270
|
-
color:
|
|
322
|
+
color: var(--calendar-accent);
|
|
271
323
|
cursor: pointer;
|
|
272
324
|
text-decoration: none;
|
|
273
325
|
padding: 4px 8px;
|
|
274
|
-
border: 1px solid
|
|
326
|
+
border: 1px solid var(--calendar-accent);
|
|
275
327
|
border-radius: 4px;
|
|
276
328
|
}
|
|
277
329
|
|
|
278
330
|
.calendar-event-join:hover {
|
|
279
|
-
background:
|
|
331
|
+
background: var(--calendar-hover);
|
|
280
332
|
}
|
|
281
333
|
|
|
282
334
|
.calendar-event-row--current,
|
|
283
335
|
.calendar-event-row--selected {
|
|
284
|
-
background:
|
|
336
|
+
background: var(--calendar-highlight);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Explicit dark and system-dark use exactly the same palette. The media query
|
|
340
|
+
only assigns tokens on system roots, never on their descendants. */
|
|
341
|
+
.calendar-pane[data-calendar-theme='dark'],
|
|
342
|
+
.calendar-selector[data-calendar-theme='dark'] {
|
|
343
|
+
--calendar-scheme: dark;
|
|
344
|
+
--calendar-surface: #1a1a1a;
|
|
345
|
+
--calendar-text: #eee;
|
|
346
|
+
--calendar-border: #333;
|
|
347
|
+
--calendar-prompt: #ccc;
|
|
348
|
+
--calendar-accent: #22d0ef;
|
|
349
|
+
--calendar-hover: #2a2a2a;
|
|
350
|
+
--calendar-chip-text: #eee;
|
|
351
|
+
--calendar-chip-border: #444;
|
|
352
|
+
--calendar-chip-selected: #22d0ef;
|
|
353
|
+
--calendar-chip-selected-text: #081a59;
|
|
354
|
+
--calendar-badge: #081a59;
|
|
355
|
+
--calendar-badge-text: #e8eefb;
|
|
356
|
+
--calendar-header: #222;
|
|
357
|
+
--calendar-allday: #2a2510;
|
|
358
|
+
--calendar-highlight: #10262b;
|
|
359
|
+
--calendar-insert: #999;
|
|
360
|
+
--calendar-insert-hover: #eee;
|
|
361
|
+
--calendar-insert-background: rgba(255, 255, 255, 0.1);
|
|
362
|
+
--calendar-focus: #22d0ef;
|
|
363
|
+
--calendar-rsvp-accepted: #4ade80;
|
|
364
|
+
--calendar-rsvp-tentative: #fbbf24;
|
|
365
|
+
--calendar-rsvp-needsAction: #60a5fa;
|
|
366
|
+
--calendar-rsvp-declined: #f87171;
|
|
367
|
+
--calendar-selector-border: #333;
|
|
368
|
+
--calendar-selector-text: #eee;
|
|
369
|
+
--calendar-selector-shadow: 0 4px 14px rgb(0 0 0 / 50%);
|
|
370
|
+
--calendar-control-border: #444;
|
|
371
|
+
--calendar-control-background: #2a2a2a;
|
|
372
|
+
--calendar-input-background: #2a2a2a;
|
|
373
|
+
--calendar-control-text: #eee;
|
|
374
|
+
--calendar-control-width: 1px;
|
|
375
|
+
--calendar-button-border-style: solid;
|
|
376
|
+
--calendar-input-border-style: solid;
|
|
377
|
+
--calendar-option-hover: #2a2a2a;
|
|
378
|
+
--calendar-option-active: #10262b;
|
|
285
379
|
}
|
|
286
380
|
|
|
287
381
|
@media (prefers-color-scheme: dark) {
|
|
288
|
-
.calendar-pane-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
background:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
border-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
.calendar-rsvp-chip-badge {
|
|
327
|
-
background: #081a59;
|
|
328
|
-
color: #e8eefb;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
.calendar-day-header {
|
|
332
|
-
background: #222;
|
|
333
|
-
color: #eee;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.calendar-event-allday {
|
|
337
|
-
border-bottom-color: #333;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.calendar-event-row {
|
|
341
|
-
border-bottom-color: #333;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
.calendar-event-allday {
|
|
345
|
-
background: #2a2510;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
.calendar-event-row--rsvp-accepted {
|
|
349
|
-
--rsvp-bar: #4ade80;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.calendar-event-row--rsvp-tentative {
|
|
353
|
-
--rsvp-bar: #fbbf24;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.calendar-event-row--rsvp-needsAction {
|
|
357
|
-
--rsvp-bar: #60a5fa;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
.calendar-event-row--rsvp-declined {
|
|
361
|
-
--rsvp-bar: #f87171;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.calendar-event-title {
|
|
365
|
-
color: #eee;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.calendar-event-join {
|
|
369
|
-
color: #22d0ef;
|
|
370
|
-
border-color: #22d0ef;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
.calendar-event-join:hover {
|
|
374
|
-
background: #2a2a2a;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
.calendar-event-row--current,
|
|
378
|
-
.calendar-event-row--selected {
|
|
379
|
-
background: #10262b;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
.calendar-event-insert-link {
|
|
383
|
-
color: #999;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
.calendar-event-insert-link:hover {
|
|
387
|
-
color: #eee;
|
|
388
|
-
background: rgba(255, 255, 255, 0.1);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
.calendar-event-insert-link:focus-visible {
|
|
392
|
-
outline-color: #22d0ef;
|
|
393
|
-
color: #eee;
|
|
382
|
+
.calendar-pane[data-calendar-theme='system'],
|
|
383
|
+
.calendar-selector[data-calendar-theme='system'] {
|
|
384
|
+
--calendar-scheme: dark;
|
|
385
|
+
--calendar-surface: #1a1a1a;
|
|
386
|
+
--calendar-text: #eee;
|
|
387
|
+
--calendar-border: #333;
|
|
388
|
+
--calendar-prompt: #ccc;
|
|
389
|
+
--calendar-accent: #22d0ef;
|
|
390
|
+
--calendar-hover: #2a2a2a;
|
|
391
|
+
--calendar-chip-text: #eee;
|
|
392
|
+
--calendar-chip-border: #444;
|
|
393
|
+
--calendar-chip-selected: #22d0ef;
|
|
394
|
+
--calendar-chip-selected-text: #081a59;
|
|
395
|
+
--calendar-badge: #081a59;
|
|
396
|
+
--calendar-badge-text: #e8eefb;
|
|
397
|
+
--calendar-header: #222;
|
|
398
|
+
--calendar-allday: #2a2510;
|
|
399
|
+
--calendar-highlight: #10262b;
|
|
400
|
+
--calendar-insert: #999;
|
|
401
|
+
--calendar-insert-hover: #eee;
|
|
402
|
+
--calendar-insert-background: rgba(255, 255, 255, 0.1);
|
|
403
|
+
--calendar-focus: #22d0ef;
|
|
404
|
+
--calendar-rsvp-accepted: #4ade80;
|
|
405
|
+
--calendar-rsvp-tentative: #fbbf24;
|
|
406
|
+
--calendar-rsvp-needsAction: #60a5fa;
|
|
407
|
+
--calendar-rsvp-declined: #f87171;
|
|
408
|
+
--calendar-selector-border: #333;
|
|
409
|
+
--calendar-selector-text: #eee;
|
|
410
|
+
--calendar-selector-shadow: 0 4px 14px rgb(0 0 0 / 50%);
|
|
411
|
+
--calendar-control-border: #444;
|
|
412
|
+
--calendar-control-background: #2a2a2a;
|
|
413
|
+
--calendar-input-background: #2a2a2a;
|
|
414
|
+
--calendar-control-text: #eee;
|
|
415
|
+
--calendar-control-width: 1px;
|
|
416
|
+
--calendar-button-border-style: solid;
|
|
417
|
+
--calendar-input-border-style: solid;
|
|
418
|
+
--calendar-option-hover: #2a2a2a;
|
|
419
|
+
--calendar-option-active: #10262b;
|
|
394
420
|
}
|
|
395
421
|
}
|
|
396
422
|
|
|
@@ -398,6 +424,12 @@
|
|
|
398
424
|
position: relative;
|
|
399
425
|
}
|
|
400
426
|
|
|
427
|
+
.calendar-selector > [role='combobox'] {
|
|
428
|
+
color: var(--calendar-control-text);
|
|
429
|
+
background: var(--calendar-control-background);
|
|
430
|
+
border-color: var(--calendar-control-border);
|
|
431
|
+
}
|
|
432
|
+
|
|
401
433
|
.calendar-selector-dropdown {
|
|
402
434
|
position: absolute;
|
|
403
435
|
z-index: 3;
|
|
@@ -405,11 +437,11 @@
|
|
|
405
437
|
min-width: 220px;
|
|
406
438
|
max-width: min(320px, calc(100vw - 32px));
|
|
407
439
|
padding: 8px;
|
|
408
|
-
border: 1px solid
|
|
440
|
+
border: 1px solid var(--calendar-selector-border);
|
|
409
441
|
border-radius: 6px;
|
|
410
|
-
background:
|
|
411
|
-
color:
|
|
412
|
-
box-shadow:
|
|
442
|
+
background: var(--calendar-surface);
|
|
443
|
+
color: var(--calendar-selector-text);
|
|
444
|
+
box-shadow: var(--calendar-selector-shadow);
|
|
413
445
|
}
|
|
414
446
|
|
|
415
447
|
.calendar-selector-dropdown--upward {
|
|
@@ -420,13 +452,22 @@
|
|
|
420
452
|
.calendar-selector-dropdown input[type='search'] {
|
|
421
453
|
box-sizing: border-box;
|
|
422
454
|
width: 100%;
|
|
455
|
+
border: var(--calendar-control-width) var(--calendar-input-border-style) var(--calendar-control-border);
|
|
456
|
+
background: var(--calendar-input-background);
|
|
457
|
+
color: var(--calendar-control-text);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.calendar-selector-dropdown button {
|
|
461
|
+
border: var(--calendar-control-width) var(--calendar-button-border-style) var(--calendar-control-border);
|
|
462
|
+
background: var(--calendar-control-background);
|
|
463
|
+
color: var(--calendar-control-text);
|
|
423
464
|
}
|
|
424
465
|
|
|
425
466
|
.calendar-selector-checkbox {
|
|
426
467
|
flex: none;
|
|
427
468
|
margin: 0;
|
|
428
469
|
pointer-events: none;
|
|
429
|
-
accent-color:
|
|
470
|
+
accent-color: var(--calendar-checkbox);
|
|
430
471
|
}
|
|
431
472
|
|
|
432
473
|
.calendar-selector-actions {
|
|
@@ -450,11 +491,16 @@
|
|
|
450
491
|
padding: 6px;
|
|
451
492
|
border: 0;
|
|
452
493
|
background: transparent;
|
|
494
|
+
color: var(--calendar-control-text);
|
|
453
495
|
text-align: left;
|
|
454
496
|
}
|
|
455
497
|
|
|
498
|
+
.calendar-selector-dropdown [role='option']:hover {
|
|
499
|
+
background: var(--calendar-option-hover);
|
|
500
|
+
}
|
|
501
|
+
|
|
456
502
|
.calendar-selector-dropdown [role='option'][data-active='true'] {
|
|
457
|
-
background:
|
|
503
|
+
background: var(--calendar-option-active);
|
|
458
504
|
}
|
|
459
505
|
|
|
460
506
|
.calendar-selector-dot {
|
|
@@ -471,41 +517,6 @@
|
|
|
471
517
|
white-space: nowrap;
|
|
472
518
|
}
|
|
473
519
|
|
|
474
|
-
@media (prefers-color-scheme: dark) {
|
|
475
|
-
.calendar-selector-dropdown {
|
|
476
|
-
border-color: #333;
|
|
477
|
-
background: #1a1a1a;
|
|
478
|
-
color: #eee;
|
|
479
|
-
box-shadow: 0 4px 14px rgb(0 0 0 / 50%);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
.calendar-selector-dropdown input[type='search'] {
|
|
483
|
-
border: 1px solid #444;
|
|
484
|
-
background: #2a2a2a;
|
|
485
|
-
color: #eee;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
.calendar-selector-dropdown button {
|
|
489
|
-
border: 1px solid #444;
|
|
490
|
-
background: #2a2a2a;
|
|
491
|
-
color: #eee;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
.calendar-selector-dropdown [role='option'] {
|
|
495
|
-
border: 0;
|
|
496
|
-
background: transparent;
|
|
497
|
-
color: #eee;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
.calendar-selector-dropdown [role='option']:hover {
|
|
501
|
-
background: #2a2a2a;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
.calendar-selector-dropdown [role='option'][data-active='true'] {
|
|
505
|
-
background: #10262b;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
520
|
.calendar-event-source-dot {
|
|
510
521
|
display: inline-block;
|
|
511
522
|
width: 8px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-webapp/calendar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsc && cp src/react/styles.css dist/styles.css",
|
|
27
|
-
"test": "vitest run"
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:theme-browser": "vitest run --config vitest.browser.config.ts"
|
|
28
29
|
},
|
|
29
30
|
"peerDependencies": {
|
|
30
31
|
"react": "^19",
|
|
@@ -37,8 +38,10 @@
|
|
|
37
38
|
"@testing-library/user-event": "^14.6.8",
|
|
38
39
|
"@types/react": "^19.0.0",
|
|
39
40
|
"@types/react-dom": "^19.0.0",
|
|
41
|
+
"@vitest/browser": "2.1.9",
|
|
40
42
|
"fake-indexeddb": "^6.0.0",
|
|
41
43
|
"jsdom": "^30.0.1",
|
|
44
|
+
"playwright": "1.51.1",
|
|
42
45
|
"react": "^19.0.0",
|
|
43
46
|
"react-dom": "^19.0.0",
|
|
44
47
|
"typescript": "^5.6.0",
|