@odx/foundation 1.0.0-rc.0 → 1.0.0-rc.10

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.
@@ -1,63 +1,64 @@
1
1
  function parseDate(value) {
2
- const createDate = (value2) => Number.isNaN(value2) ? null : new Date(value2);
3
- if (value instanceof Date) {
4
- return createDate(value.getTime());
5
- }
6
- const date = new Date(value);
7
- if (Number.isNaN(date.getTime()) && typeof value === "string") {
8
- return createDate(Number(value));
9
- }
10
- return createDate(date.getTime());
2
+ const createDate = (value) => Number.isNaN(value) ? null : new Date(value);
3
+ if (value instanceof Date) return createDate(value.getTime());
4
+ const date = new Date(value);
5
+ if (Number.isNaN(date.getTime()) && typeof value === "string") return createDate(Number(value));
6
+ return createDate(date.getTime());
11
7
  }
12
8
  function formatDate(input, options) {
13
- const value = parseDate(input);
14
- if (!value) return "";
15
- if (options?.dateStyle === "iso8601") {
16
- return new Intl.DateTimeFormat("sv-SE", { dateStyle: "short" }).format(value);
17
- }
18
- return new Intl.DateTimeFormat(options?.locale, options).format(value);
9
+ const value = parseDate(input);
10
+ if (!value) return "";
11
+ if (options?.dateStyle === "iso8601") return new Intl.DateTimeFormat("sv-SE", { dateStyle: "short" }).format(value);
12
+ return new Intl.DateTimeFormat(options?.locale, options).format(value);
19
13
  }
20
14
  function formatNumber(input, options) {
21
- const value = Number(input);
22
- if (Number.isNaN(value)) return "";
23
- if (options?.currency) {
24
- options.style = "currency";
25
- } else if (options?.unit) {
26
- options.style = "unit";
27
- }
28
- return new Intl.NumberFormat(options?.locale, options).format(value);
15
+ const value = Number(input);
16
+ if (Number.isNaN(value)) return "";
17
+ if (options?.currency) options.style = "currency";
18
+ else if (options?.unit) options.style = "unit";
19
+ return new Intl.NumberFormat(options?.locale, options).format(value);
29
20
  }
30
21
  function formatList(input, options) {
31
- if (input.length === 0) return "";
32
- return new Intl.ListFormat(options?.locale, options).format(input);
22
+ if (input.length === 0) return "";
23
+ return new Intl.ListFormat(options?.locale, options).format(input);
33
24
  }
34
25
  const TIME_UNIT_MAP = {
35
- second: { max: 59e3, value: 1e3 },
36
- // max 59 seconds
37
- minute: { max: 276e4, value: 6e4 },
38
- // max 46 minutes
39
- hour: { max: 72e6, value: 36e5 },
40
- // max 20 hours
41
- day: { max: 5184e5, value: 864e5 },
42
- // max 6 days
43
- week: { max: 24192e5, value: 6048e5 },
44
- // max 28 days
45
- month: { max: 28512e6, value: 2592e6 },
46
- // max 11 months
47
- year: { max: Number.POSITIVE_INFINITY, value: 31536e6 }
26
+ second: {
27
+ max: 59e3,
28
+ value: 1e3
29
+ },
30
+ minute: {
31
+ max: 276e4,
32
+ value: 6e4
33
+ },
34
+ hour: {
35
+ max: 72e6,
36
+ value: 36e5
37
+ },
38
+ day: {
39
+ max: 5184e5,
40
+ value: 864e5
41
+ },
42
+ week: {
43
+ max: 24192e5,
44
+ value: 6048e5
45
+ },
46
+ month: {
47
+ max: 28512e6,
48
+ value: 2592e6
49
+ },
50
+ year: {
51
+ max: Number.POSITIVE_INFINITY,
52
+ value: 31536e6
53
+ }
48
54
  };
49
55
  function formatRelativeTime(input, options) {
50
- const value = parseDate(input);
51
- if (!value) return "";
52
- const relativeTime = value.getTime() - Date.now();
53
- const minUnit = options?.minUnit && TIME_UNIT_MAP[options.minUnit] || TIME_UNIT_MAP.second;
54
- const [unit, unitConfig] = Object.entries(TIME_UNIT_MAP).find(
55
- ([_, { value: value2, max }]) => Math.abs(relativeTime) < max && minUnit.value <= value2
56
- );
57
- return new Intl.RelativeTimeFormat(options?.locale, options).format(
58
- Math.round(relativeTime / unitConfig.value),
59
- unit
60
- );
56
+ const startDate = parseDate(options?.start ?? Date.now());
57
+ const value = parseDate(input);
58
+ if (!value || !startDate) return "";
59
+ const relativeTime = value.getTime() - startDate.getTime();
60
+ const minUnit = options?.minUnit && TIME_UNIT_MAP[options.minUnit] || TIME_UNIT_MAP.second;
61
+ const [unit, unitConfig] = Object.entries(TIME_UNIT_MAP).find(([_, { value, max }]) => Math.abs(relativeTime) < max && minUnit.value <= value);
62
+ return new Intl.RelativeTimeFormat(options?.locale, options).format(Math.round(relativeTime / unitConfig.value), unit);
61
63
  }
62
-
63
64
  export { formatDate, formatList, formatNumber, formatRelativeTime, parseDate };
@@ -1,12 +1,12 @@
1
- import { FormatOptions } from './format.js';
2
- export interface LocalizationOptions extends FormatOptions {
3
- defaultLocale: () => Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier;
4
- fallbackLanguage: () => Intl.UnicodeBCP47LocaleIdentifier;
5
- fallbackTranslation: (key: string) => string;
1
+ import { FormatOptions } from "./format.js";
2
+ interface LocalizationOptions extends FormatOptions {
3
+ defaultLocale: () => Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier;
4
+ fallbackLanguage: () => Intl.UnicodeBCP47LocaleIdentifier;
5
+ fallbackTranslation: (key: string) => string;
6
6
  }
7
- export declare const LocalizationOptions: (config?: Partial<LocalizationOptions>) => LocalizationOptions;
8
- export declare function setLocalizationOptions(options?: Partial<LocalizationOptions> | null): void;
9
- export declare function getLocalizationOptions(options?: Partial<LocalizationOptions> | null): LocalizationOptions;
10
- export declare function getLocale(localeInput?: Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier | null): Intl.Locale;
11
- export declare function setLocale(localeInput?: Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier | null): void;
12
- //# sourceMappingURL=localization.d.ts.map
7
+ declare const LocalizationOptions: (config?: Partial<LocalizationOptions>) => LocalizationOptions;
8
+ declare function setLocalizationOptions(options?: Partial<LocalizationOptions> | null): void;
9
+ declare function getLocalizationOptions(options?: Partial<LocalizationOptions> | null): LocalizationOptions;
10
+ declare function getLocale(localeInput?: Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier | null): Intl.Locale;
11
+ declare function setLocale(localeInput?: Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier | null): void;
12
+ export { LocalizationOptions, getLocale, getLocalizationOptions, setLocale, setLocalizationOptions };
@@ -1,28 +1,26 @@
1
- import { sharedSignal } from './signals.js';
2
-
1
+ import { sharedSignal } from "./signals.js";
3
2
  const locale = sharedSignal("locale", null);
4
3
  const localizationOptions = sharedSignal("localizationOptions", null);
5
4
  const LocalizationOptions = (config) => ({
6
- defaultLocale: () => navigator.language,
7
- fallbackLanguage: () => "en",
8
- fallbackTranslation: (key) => key,
9
- ...config,
10
- relativeTimeFormatOptions: {
11
- minUnit: "minute",
12
- ...config?.relativeTimeFormatOptions
13
- }
5
+ defaultLocale: () => navigator.language,
6
+ fallbackLanguage: () => "en",
7
+ fallbackTranslation: (key) => key,
8
+ ...config,
9
+ relativeTimeFormatOptions: {
10
+ minUnit: "minute",
11
+ ...config?.relativeTimeFormatOptions
12
+ }
14
13
  });
15
14
  function setLocalizationOptions(options) {
16
- localizationOptions.set(getLocalizationOptions(options));
15
+ localizationOptions.set(getLocalizationOptions(options));
17
16
  }
18
17
  function getLocalizationOptions(options) {
19
- return LocalizationOptions(options ?? localizationOptions.get() ?? {});
18
+ return LocalizationOptions(options ?? localizationOptions.get() ?? {});
20
19
  }
21
20
  function getLocale(localeInput) {
22
- return new Intl.Locale(localeInput || locale.get() || getLocalizationOptions().defaultLocale());
21
+ return new Intl.Locale(localeInput || locale.get() || getLocalizationOptions().defaultLocale());
23
22
  }
24
23
  function setLocale(localeInput) {
25
- locale.set(localeInput ? getLocale(localeInput) : null);
24
+ locale.set(localeInput ? getLocale(localeInput) : null);
26
25
  }
27
-
28
26
  export { LocalizationOptions, getLocale, getLocalizationOptions, setLocale, setLocalizationOptions };
@@ -1,39 +1,3 @@
1
- export type Alignment = (typeof Alignment)[keyof typeof Alignment];
2
- export declare const Alignment: {
3
- readonly START: "start";
4
- readonly CENTER: "center";
5
- readonly END: "end";
6
- };
7
- export type Spacing = (typeof Spacing)[keyof typeof Spacing];
8
- export declare const Spacing: {
9
- readonly 0: "0";
10
- readonly SM: "sm";
11
- readonly MD: "md";
12
- readonly LG: "lg";
13
- };
14
- export type Justify = (typeof Justify)[keyof typeof Justify];
15
- export declare const Justify: {
16
- readonly START: "start";
17
- readonly END: "end";
18
- readonly CENTER: "center";
19
- readonly SPACE_BETWEEN: "space-between";
20
- readonly SPACE_AROUND: "space-around";
21
- readonly SPACE_EVENLY: "space-evenly";
22
- };
23
- export type Variant = (typeof Variant)[keyof typeof Variant];
24
- export declare const Variant: {
25
- readonly NEUTRAL: "neutral";
26
- readonly PRIMARY: "primary";
27
- readonly ACCENT: "accent";
28
- readonly SUCCESS: "success";
29
- readonly WARNING: "warning";
30
- readonly DANGER: "danger";
31
- readonly ACCENT_GHOST: "accent-ghost";
32
- readonly DANGER_GHOST: "danger-ghost";
33
- readonly CONFIRMATION: "confirmation";
34
- readonly SUBTLE: "subtle";
35
- readonly GHOST: "ghost";
36
- };
37
- export type UnitIdentifier = SingleUnitIdentifier | `${SingleUnitIdentifier}-per-${SingleUnitIdentifier}` | (string & {});
38
- export type SingleUnitIdentifier = 'acre' | 'bit' | 'byte' | 'celsius' | 'centimeter' | 'day' | 'degree' | 'fahrenheit' | 'fluid-ounce' | 'foot' | 'gallon' | 'gigabit' | 'gigabyte' | 'gram' | 'hectare' | 'hour' | 'inch' | 'kilobit' | 'kilobyte' | 'kilogram' | 'kilometer' | 'liter' | 'megabit' | 'megabyte' | 'meter' | 'microsecond' | 'mile' | 'mile-scandinavian' | 'milliliter' | 'millimeter' | 'millisecond' | 'minute' | 'month' | 'nanosecond' | 'ounce' | 'percent' | 'petabyte' | 'pound' | 'second' | 'stone' | 'terabit' | 'terabyte' | 'week' | 'yard' | 'year';
39
- //# sourceMappingURL=models.d.ts.map
1
+ type UnitIdentifier = SingleUnitIdentifier | `${SingleUnitIdentifier}-per-${SingleUnitIdentifier}` | (string & {});
2
+ type SingleUnitIdentifier = 'acre' | 'bit' | 'byte' | 'celsius' | 'centimeter' | 'day' | 'degree' | 'fahrenheit' | 'fluid-ounce' | 'foot' | 'gallon' | 'gigabit' | 'gigabyte' | 'gram' | 'hectare' | 'hour' | 'inch' | 'kilobit' | 'kilobyte' | 'kilogram' | 'kilometer' | 'liter' | 'megabit' | 'megabyte' | 'meter' | 'microsecond' | 'mile' | 'mile-scandinavian' | 'milliliter' | 'millimeter' | 'millisecond' | 'minute' | 'month' | 'nanosecond' | 'ounce' | 'percent' | 'petabyte' | 'pound' | 'second' | 'stone' | 'terabit' | 'terabyte' | 'week' | 'yard' | 'year';
3
+ export { UnitIdentifier };
@@ -0,0 +1,7 @@
1
+ /** @internal */
2
+ declare function applyScrollLock(source: HTMLElement): void;
3
+ /** @internal */
4
+ declare function removeScrollLock(source: HTMLElement): void;
5
+ /** @internal */
6
+ declare function removeAllScrollLocks(): void;
7
+ export { applyScrollLock, removeAllScrollLocks, removeScrollLock };
@@ -0,0 +1,27 @@
1
+ const scrollLockClass = "odx-scroll-lock";
2
+ const scrollLocks = /* @__PURE__ */ new Set();
3
+ /** @internal */
4
+ function applyScrollLock(source) {
5
+ const { documentElement } = document;
6
+ scrollLocks.add(source);
7
+ if (documentElement.classList.contains(scrollLockClass)) return;
8
+ const bodyPadding = Number(getComputedStyle(document.body).paddingRight.replace("px", ""));
9
+ let scrollbarWidth = Math.abs(window.innerWidth - documentElement.clientWidth);
10
+ if (!Number.isNaN(bodyPadding) && bodyPadding > 0) scrollbarWidth += bodyPadding;
11
+ let { scrollbarGutter } = getComputedStyle(documentElement);
12
+ if (!scrollbarGutter || scrollbarGutter === "auto") scrollbarGutter = "stable";
13
+ documentElement.classList.add(scrollLockClass);
14
+ documentElement.style.setProperty("--odx-scroll-lock-gutter", scrollbarWidth > 1 ? scrollbarGutter : "");
15
+ }
16
+ /** @internal */
17
+ function removeScrollLock(source) {
18
+ scrollLocks.delete(source);
19
+ if (scrollLocks.size > 0) return;
20
+ document.documentElement.classList.remove(scrollLockClass);
21
+ }
22
+ /** @internal */
23
+ function removeAllScrollLocks() {
24
+ scrollLocks.clear();
25
+ document.documentElement.classList.remove(scrollLockClass);
26
+ }
27
+ export { applyScrollLock, removeAllScrollLocks, removeScrollLock };
@@ -1,20 +1,20 @@
1
- import { Signal as NativeSignal } from 'signal-polyfill';
2
- export type Signal<T> = NativeSignal.State<T> & {
3
- update: (updateFn: (value: T) => T) => void;
1
+ import { Signal } from "signal-polyfill";
2
+ type Signal$1<T> = Signal.State<T> & {
3
+ update: (updateFn: (value: T) => T) => void;
4
4
  };
5
- export type SignalOptions<T> = NativeSignal.Options<T> & {
6
- watched?(): void;
7
- unwatched?(): void;
5
+ type SignalOptions<T> = Signal.Options<T> & {
6
+ watched?(): void;
7
+ unwatched?(): void;
8
8
  };
9
- export type ReadonlySignal<T> = NativeSignal.Computed<T>;
10
- export declare function signal<T>(value: T, options?: SignalOptions<T>): Signal<T>;
9
+ type ReadonlySignal<T> = Signal.Computed<T>;
10
+ declare function signal<T>(value: T, options?: SignalOptions<T>): Signal$1<T>;
11
11
  /**
12
12
  * Creates or retrieves a shared signal stored on the global object. This is useful for signals that need to be shared across multiple modules without explicitly passing them around, such as localization settings or translation records.
13
13
  */
14
- export declare function sharedSignal<T>(key: string, ...args: Parameters<typeof signal<T>>): ReturnType<typeof signal<T>>;
15
- export declare function computed<T>(computeFn: () => T, options?: SignalOptions<T>): ReadonlySignal<T>;
16
- export declare function effect(callback: (() => void) | (() => () => void)): () => void;
14
+ declare function sharedSignal<T>(key: string, ...args: Parameters<typeof signal<T>>): ReturnType<typeof signal<T>>;
15
+ declare function computed<T>(computeFn: () => T, options?: SignalOptions<T>): ReadonlySignal<T>;
16
+ declare function effect(callback: (() => void) | (() => () => void)): () => void;
17
17
  declare global {
18
- var __ODX_SHARED_SIGNALS__: Record<string, unknown>;
18
+ var __ODX_SHARED_SIGNALS__: Record<string, unknown>;
19
19
  }
20
- //# sourceMappingURL=signals.d.ts.map
20
+ export { ReadonlySignal, Signal$1 as Signal, SignalOptions, computed, effect, sharedSignal, signal };
@@ -1,47 +1,50 @@
1
- import { Signal } from 'signal-polyfill';
2
-
1
+ import { Signal } from "signal-polyfill";
3
2
  function transformOptions(options) {
4
- if (!options) return;
5
- return { equals: options.equals, [Signal.subtle.watched]: options.watched, [Signal.subtle.unwatched]: options.unwatched };
3
+ if (!options) return;
4
+ return {
5
+ equals: options.equals,
6
+ [Signal.subtle.watched]: options.watched,
7
+ [Signal.subtle.unwatched]: options.unwatched
8
+ };
6
9
  }
7
10
  function signal(value, options) {
8
- const state = new Signal.State(value, transformOptions(options));
9
- state.update = (updateFn) => state.set(updateFn(state.get()));
10
- return state;
11
+ const state = new Signal.State(value, transformOptions(options));
12
+ state.update = (updateFn) => state.set(updateFn(state.get()));
13
+ return state;
11
14
  }
15
+ /**
16
+ * Creates or retrieves a shared signal stored on the global object. This is useful for signals that need to be shared across multiple modules without explicitly passing them around, such as localization settings or translation records.
17
+ */
12
18
  function sharedSignal(key, ...args) {
13
- if (!(key in globalThis.__ODX_SHARED_SIGNALS__)) {
14
- globalThis.__ODX_SHARED_SIGNALS__[key] = signal(...args);
15
- }
16
- return globalThis.__ODX_SHARED_SIGNALS__[key];
19
+ if (!(key in globalThis.__ODX_SHARED_SIGNALS__)) globalThis.__ODX_SHARED_SIGNALS__[key] = signal(...args);
20
+ return globalThis.__ODX_SHARED_SIGNALS__[key];
17
21
  }
18
22
  function computed(computeFn, options) {
19
- return new Signal.Computed(computeFn, transformOptions(options));
23
+ return new Signal.Computed(computeFn, transformOptions(options));
20
24
  }
21
25
  let needsEnqueue = true;
22
26
  const watcher = new Signal.subtle.Watcher(() => {
23
- if (!needsEnqueue) return;
24
- needsEnqueue = false;
25
- queueMicrotask(() => {
26
- needsEnqueue = true;
27
- for (const signal2 of watcher.getPending()) signal2.get();
28
- watcher.watch();
29
- });
27
+ if (!needsEnqueue) return;
28
+ needsEnqueue = false;
29
+ queueMicrotask(() => {
30
+ needsEnqueue = true;
31
+ for (const signal of watcher.getPending()) signal.get();
32
+ watcher.watch();
33
+ });
30
34
  });
31
35
  function effect(callback) {
32
- let cleanup;
33
- const signal2 = computed(() => {
34
- cleanup?.();
35
- cleanup = callback() || void 0;
36
- });
37
- watcher.watch(signal2);
38
- signal2.get();
39
- return () => {
40
- watcher.unwatch(signal2);
41
- cleanup?.();
42
- cleanup = void 0;
43
- };
36
+ let cleanup;
37
+ const signal = computed(() => {
38
+ cleanup?.();
39
+ cleanup = callback() || void 0;
40
+ });
41
+ watcher.watch(signal);
42
+ signal.get();
43
+ return () => {
44
+ watcher.unwatch(signal);
45
+ cleanup?.();
46
+ cleanup = void 0;
47
+ };
44
48
  }
45
49
  globalThis.__ODX_SHARED_SIGNALS__ ||= {};
46
-
47
50
  export { computed, effect, sharedSignal, signal };
@@ -1,18 +1,16 @@
1
- import { ThemeConfig } from '@odx/design-tokens';
2
- import { ReadonlySignal } from './signals.js';
1
+ import { ThemeConfig } from "@odx/design-tokens";
3
2
  declare global {
4
- var odxDarkModeEnabled: ReadonlySignal<boolean> | undefined;
5
- var __ODX_THEME_ROOT__: HTMLElement;
3
+ var __ODX_THEME_ROOT__: HTMLElement;
6
4
  }
7
- export declare const userPrefersDarkMode: boolean;
8
- export declare const darkModeIcon = "core::night-mode";
9
- export declare const lightModeIcon = "core::brightness";
10
- export declare function setTheme(config: ThemeConfig, root?: HTMLElement): void;
11
- export declare function isDarkModeEnabled(): boolean;
12
- export declare function toggleDarkMode(enabled?: boolean | 'auto', root?: HTMLElement): void;
13
- export interface AttachDarkModeToggleOptions<T extends HTMLElement> {
14
- update?(host: T, darkModeEnabled: boolean, icon: string): void;
15
- root?: HTMLElement;
5
+ declare const userPrefersDarkMode: boolean;
6
+ declare const darkModeIcon = "core::night-mode";
7
+ declare const lightModeIcon = "core::brightness";
8
+ declare function setTheme$1(config: ThemeConfig, root?: HTMLElement): void;
9
+ declare function isDarkModeEnabled(): boolean;
10
+ declare function toggleDarkMode(enabled?: boolean | 'auto', root?: HTMLElement): void;
11
+ interface AttachDarkModeToggleOptions<T extends HTMLElement> {
12
+ update?(host: T, darkModeEnabled: boolean, icon: string): void;
13
+ root?: HTMLElement;
16
14
  }
17
- export declare function attachDarkModeToggle<T extends HTMLElement>(host: T, options?: AttachDarkModeToggleOptions<T>): () => void;
18
- //# sourceMappingURL=theming.d.ts.map
15
+ declare function attachDarkModeToggle<T extends HTMLElement>(host: T, options?: AttachDarkModeToggleOptions<T>): () => void;
16
+ export { AttachDarkModeToggleOptions, attachDarkModeToggle, darkModeIcon, isDarkModeEnabled, lightModeIcon, setTheme$1 as setTheme, toggleDarkMode, userPrefersDarkMode };
@@ -1,38 +1,32 @@
1
- import { darkModeClass, lightModeClass, setTheme as setTheme$1 } from '@odx/design-tokens';
2
- import { sharedSignal, effect } from './signals.js';
3
-
1
+ import { effect, sharedSignal } from "./signals.js";
2
+ import { darkModeClass, lightModeClass, setTheme } from "@odx/design-tokens";
4
3
  const { matches: userPrefersDarkMode = false } = globalThis.matchMedia?.("(prefers-color-scheme: dark)") ?? {};
5
4
  const darkModeIcon = "core::night-mode";
6
5
  const lightModeIcon = "core::brightness";
7
- const hasDarkModeClass = document.documentElement.classList.contains(darkModeClass);
8
- const hasLightModeClass = document.documentElement.classList.contains(lightModeClass);
9
- const darkModeEnabled = sharedSignal("darkModeEnabled", hasDarkModeClass || hasLightModeClass ? hasDarkModeClass : userPrefersDarkMode);
10
6
  globalThis.__ODX_THEME_ROOT__ ??= document.documentElement;
11
- function setTheme(config, root = globalThis.__ODX_THEME_ROOT__) {
12
- setTheme$1(config, root);
13
- if (config.mode === "auto") {
14
- darkModeEnabled.set(userPrefersDarkMode);
15
- } else {
16
- darkModeEnabled.set(config.mode === "dark" ? true : !isDarkModeEnabled());
17
- }
7
+ const hasDarkModeClass = globalThis.__ODX_THEME_ROOT__.classList.contains(darkModeClass);
8
+ const hasLightModeClass = globalThis.__ODX_THEME_ROOT__.classList.contains(lightModeClass);
9
+ const darkModeEnabled = sharedSignal("darkModeEnabled", hasDarkModeClass || hasLightModeClass ? hasDarkModeClass : userPrefersDarkMode);
10
+ function setTheme$1(config, root = globalThis.__ODX_THEME_ROOT__) {
11
+ setTheme(config, root);
12
+ if (!config.mode) return;
13
+ if (config.mode === "auto") darkModeEnabled.set(userPrefersDarkMode);
14
+ else darkModeEnabled.set(config.mode === "dark" ? true : !isDarkModeEnabled());
18
15
  }
19
16
  function isDarkModeEnabled() {
20
- return darkModeEnabled.get();
17
+ return darkModeEnabled.get();
21
18
  }
22
19
  function toggleDarkMode(enabled, root = globalThis.__ODX_THEME_ROOT__) {
23
- if (enabled === "auto") {
24
- setTheme({ mode: enabled }, root);
25
- } else {
26
- setTheme({ mode: enabled ? "dark" : "light" }, root);
27
- }
20
+ enabled ||= !isDarkModeEnabled();
21
+ setTheme$1({ mode: enabled === "auto" ? enabled : enabled ? "dark" : "light" }, root);
28
22
  }
29
23
  function attachDarkModeToggle(host, options = {}) {
30
- host.addEventListener("click", () => toggleDarkMode(void 0, options.root));
31
- return effect(() => {
32
- const darkModeEnabled2 = isDarkModeEnabled();
33
- host.setAttribute("icon", darkModeEnabled2 ? darkModeIcon : lightModeIcon);
34
- options.update?.(host, darkModeEnabled2, darkModeEnabled2 ? darkModeIcon : lightModeIcon);
35
- });
24
+ host.addEventListener("click", () => toggleDarkMode(void 0, options.root));
25
+ return effect(() => {
26
+ const darkModeEnabled = isDarkModeEnabled();
27
+ const icon = darkModeEnabled ? lightModeIcon : darkModeIcon;
28
+ host.setAttribute("icon", icon);
29
+ options.update?.(host, darkModeEnabled, icon);
30
+ });
36
31
  }
37
-
38
- export { attachDarkModeToggle, darkModeIcon, isDarkModeEnabled, lightModeIcon, setTheme, toggleDarkMode, userPrefersDarkMode };
32
+ export { attachDarkModeToggle, darkModeIcon, isDarkModeEnabled, lightModeIcon, setTheme$1 as setTheme, toggleDarkMode, userPrefersDarkMode };
@@ -1,43 +1,39 @@
1
1
  const mediaQueryRegistry = /* @__PURE__ */ new Map();
2
2
  const eventListenerRegistry = /* @__PURE__ */ new Map();
3
3
  function handleMediaChange(event) {
4
- const listeners = eventListenerRegistry.get(event.media);
5
- if (!listeners?.size) return;
6
- const listenersArray = Array.from(listeners);
7
- let i = listenersArray.length;
8
- while (i--) {
9
- listenersArray[i]?.(event);
10
- }
4
+ const listeners = eventListenerRegistry.get(event.media);
5
+ if (!listeners?.size) return;
6
+ const listenersArray = Array.from(listeners);
7
+ let i = listenersArray.length;
8
+ while (i--) listenersArray[i]?.(event);
11
9
  }
12
10
  function observeMedia(query, listener) {
13
- let listeners = eventListenerRegistry.get(query);
14
- if (!listeners) {
15
- listeners = /* @__PURE__ */ new Set();
16
- eventListenerRegistry.set(query, listeners);
17
- }
18
- listeners.add(listener);
19
- let mediaQueryList = mediaQueryRegistry.get(query);
20
- if (!mediaQueryList) {
21
- mediaQueryList = globalThis.matchMedia(query);
22
- mediaQueryRegistry.set(query, mediaQueryList);
23
- mediaQueryList.addEventListener("change", handleMediaChange);
24
- }
25
- const initialEvent = new MediaQueryListEvent("change", {
26
- media: mediaQueryList.media,
27
- matches: mediaQueryList.matches
28
- });
29
- listener(initialEvent);
30
- return () => unobserveMedia(query, listener);
11
+ let listeners = eventListenerRegistry.get(query);
12
+ if (!listeners) {
13
+ listeners = /* @__PURE__ */ new Set();
14
+ eventListenerRegistry.set(query, listeners);
15
+ }
16
+ listeners.add(listener);
17
+ let mediaQueryList = mediaQueryRegistry.get(query);
18
+ if (!mediaQueryList) {
19
+ mediaQueryList = globalThis.matchMedia(query);
20
+ mediaQueryRegistry.set(query, mediaQueryList);
21
+ mediaQueryList.addEventListener("change", handleMediaChange);
22
+ }
23
+ listener(new MediaQueryListEvent("change", {
24
+ media: mediaQueryList.media,
25
+ matches: mediaQueryList.matches
26
+ }));
27
+ return () => unobserveMedia(query, listener);
31
28
  }
32
29
  function unobserveMedia(query, listener) {
33
- const listeners = eventListenerRegistry.get(query);
34
- if (!listeners?.delete(listener)) return;
35
- if (listeners.size > 0) return;
36
- eventListenerRegistry.delete(query);
37
- const mediaQueryList = mediaQueryRegistry.get(query);
38
- if (!mediaQueryList) return;
39
- mediaQueryList.removeEventListener("change", handleMediaChange);
40
- mediaQueryRegistry.delete(query);
30
+ const listeners = eventListenerRegistry.get(query);
31
+ if (!listeners?.delete(listener)) return;
32
+ if (listeners.size > 0) return;
33
+ eventListenerRegistry.delete(query);
34
+ const mediaQueryList = mediaQueryRegistry.get(query);
35
+ if (!mediaQueryList) return;
36
+ mediaQueryList.removeEventListener("change", handleMediaChange);
37
+ mediaQueryRegistry.delete(query);
41
38
  }
42
-
43
- export { observeMedia, unobserveMedia };
39
+ export { observeMedia };
package/dist/main.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export * from './lib/breakpoints.js';
2
- export * from './lib/format.js';
3
- export * from './lib/localization.js';
4
- export type { UnitIdentifier } from './lib/models.js';
5
- export * from './lib/signals.js';
6
- export * from './lib/theming.js';
7
- //# sourceMappingURL=main.d.ts.map
1
+ import { ReadonlySignal, Signal, SignalOptions, computed, effect, sharedSignal, signal } from "./lib/signals.js";
2
+ import { Breakpoint, BreakpointConfig, BreakpointOperator, breakpointAttribute, buildBreakpoint, createBreakpointUpdater, defaultBreakpoints, expandBreakpoints, observeBreakpoint, registeredBreakpoints, setupBreakpoints } from "./lib/breakpoints.js";
3
+ import { UnitIdentifier } from "./lib/models.js";
4
+ import { DateTimeFormatOptions, FormatOptions, ListFormatOptions, NumberFormatOptions, RelativeTimeFormatOptions, formatDate, formatList, formatNumber, formatRelativeTime, parseDate } from "./lib/format.js";
5
+ import { LocalizationOptions, getLocale, getLocalizationOptions, setLocale, setLocalizationOptions } from "./lib/localization.js";
6
+ import { applyScrollLock, removeAllScrollLocks, removeScrollLock } from "./lib/scroll-lock.js";
7
+ import { AttachDarkModeToggleOptions, attachDarkModeToggle, darkModeIcon, isDarkModeEnabled, lightModeIcon, setTheme, toggleDarkMode, userPrefersDarkMode } from "./lib/theming.js";
8
+ export { AttachDarkModeToggleOptions, Breakpoint, BreakpointConfig, BreakpointOperator, DateTimeFormatOptions, FormatOptions, ListFormatOptions, LocalizationOptions, NumberFormatOptions, ReadonlySignal, RelativeTimeFormatOptions, Signal, SignalOptions, type UnitIdentifier, applyScrollLock, attachDarkModeToggle, breakpointAttribute, buildBreakpoint, computed, createBreakpointUpdater, darkModeIcon, defaultBreakpoints, effect, expandBreakpoints, formatDate, formatList, formatNumber, formatRelativeTime, getLocale, getLocalizationOptions, isDarkModeEnabled, lightModeIcon, observeBreakpoint, parseDate, registeredBreakpoints, removeAllScrollLocks, removeScrollLock, setLocale, setLocalizationOptions, setTheme, setupBreakpoints, sharedSignal, signal, toggleDarkMode, userPrefersDarkMode };
package/dist/main.js CHANGED
@@ -1,5 +1,7 @@
1
- export { breakpointAttribute, buildBreakpoint, createBreakpointUpdater, defaultBreakpoints, expandBreakpoints, observeBreakpoint, registeredBreakpoints, setupBreakpoints } from './lib/breakpoints.js';
2
- export { formatDate, formatList, formatNumber, formatRelativeTime, parseDate } from './lib/format.js';
3
- export { LocalizationOptions, getLocale, getLocalizationOptions, setLocale, setLocalizationOptions } from './lib/localization.js';
4
- export { computed, effect, sharedSignal, signal } from './lib/signals.js';
5
- export { attachDarkModeToggle, darkModeIcon, isDarkModeEnabled, lightModeIcon, setTheme, toggleDarkMode, userPrefersDarkMode } from './lib/theming.js';
1
+ import { computed, effect, sharedSignal, signal } from "./lib/signals.js";
2
+ import { breakpointAttribute, buildBreakpoint, createBreakpointUpdater, defaultBreakpoints, expandBreakpoints, observeBreakpoint, registeredBreakpoints, setupBreakpoints } from "./lib/breakpoints.js";
3
+ import { formatDate, formatList, formatNumber, formatRelativeTime, parseDate } from "./lib/format.js";
4
+ import { LocalizationOptions, getLocale, getLocalizationOptions, setLocale, setLocalizationOptions } from "./lib/localization.js";
5
+ import { applyScrollLock, removeAllScrollLocks, removeScrollLock } from "./lib/scroll-lock.js";
6
+ import { attachDarkModeToggle, darkModeIcon, isDarkModeEnabled, lightModeIcon, setTheme, toggleDarkMode, userPrefersDarkMode } from "./lib/theming.js";
7
+ export { LocalizationOptions, applyScrollLock, attachDarkModeToggle, breakpointAttribute, buildBreakpoint, computed, createBreakpointUpdater, darkModeIcon, defaultBreakpoints, effect, expandBreakpoints, formatDate, formatList, formatNumber, formatRelativeTime, getLocale, getLocalizationOptions, isDarkModeEnabled, lightModeIcon, observeBreakpoint, parseDate, registeredBreakpoints, removeAllScrollLocks, removeScrollLock, setLocale, setLocalizationOptions, setTheme, setupBreakpoints, sharedSignal, signal, toggleDarkMode, userPrefersDarkMode };