@odx/foundation 1.0.0-beta.232 → 1.0.0-beta.234

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,13 +1,4 @@
1
- import { Breakpoint, BreakpointPlugin } from './models.js';
2
- declare global {
3
- namespace ODX {
4
- interface Breakpoints {
5
- mobile: true;
6
- tablet: true;
7
- desktop: true;
8
- }
9
- }
10
- }
1
+ import { BreakpointConfig } from './models.js';
11
2
  export declare const defaultBreakpoints: {
12
3
  readonly mobile: {
13
4
  readonly id: "mobile";
@@ -25,12 +16,8 @@ export declare const defaultBreakpoints: {
25
16
  readonly max: 1199.98;
26
17
  };
27
18
  };
28
- export interface BreakpointsConfig {
29
- breakpoints: Breakpoint[];
30
- plugins: BreakpointPlugin[];
31
- }
32
- export declare const BreakpointsConfig: (config?: Partial<BreakpointsConfig>) => BreakpointsConfig;
33
- export default function setupBreakpoints(config?: Partial<BreakpointsConfig>): () => void;
34
- export declare function getBreakpoints(): Breakpoint[];
35
- export { BreakpointClassNamePlugin, BreakpointHideTargetPlugin } from './plugins.js';
19
+ export default function setupBreakpoints(breakpointsConfig?: BreakpointConfig[], root?: HTMLElement): () => void;
20
+ export * from './models.js';
21
+ export * from './plugins.js';
22
+ export * from './utils.js';
36
23
  //# sourceMappingURL=main.d.ts.map
@@ -1,15 +1,16 @@
1
- export interface Breakpoint {
2
- id: keyof ODX.Breakpoints;
1
+ export interface BreakpointConfig {
2
+ id: string;
3
3
  min: number;
4
4
  max: number;
5
5
  customQuery?: string;
6
6
  }
7
- export type BreakpointEntry = Breakpoint & {
7
+ export type BreakpointOperator = '<' | '<=' | '>=' | '>';
8
+ export type Breakpoint = BreakpointConfig & {
8
9
  query: string;
9
10
  operator?: BreakpointOperator;
10
11
  };
11
- export type BreakpointOperator = '<' | '<=' | '>=' | '>';
12
- export type BreakpointPlugin = (target: HTMLElement, breakpoint: Breakpoint & {
12
+ export type BreakpointChange = Breakpoint & {
13
13
  matches: boolean;
14
- }) => void;
14
+ };
15
+ export type BreakpointPlugin = (target: HTMLElement, change: BreakpointChange) => void;
15
16
  //# sourceMappingURL=models.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import { Signal } from '@preact/signals-core';
2
- import { Breakpoint, BreakpointEntry } from './models.js';
3
- export declare function observeBreakpoint(breakpoint: Breakpoint & {
4
- query?: string;
5
- operator?: BreakpointEntry['operator'];
6
- }, initialValue?: boolean): Signal<Breakpoint & {
2
+ import { Breakpoint, BreakpointChange, BreakpointConfig, BreakpointOperator, BreakpointPlugin } from './models.js';
3
+ export declare const breakpointDirective: import('../utils/main.js').StringAttributeDirective<"odx-breakpoint">;
4
+ export declare function buildBreakpoint(breakpoint: BreakpointConfig, operator?: BreakpointOperator): Breakpoint;
5
+ export declare function createBreakpointHandler(plugins: BreakpointPlugin[], targets: HTMLElement[]): (change: BreakpointChange) => void;
6
+ export declare function expandBreakpoints(...breakpoints: BreakpointConfig[]): Record<string, Breakpoint>;
7
+ export declare function observeBreakpoint(breakpoint: Breakpoint, initialValue?: boolean): Signal<Breakpoint & {
7
8
  matches: boolean;
8
9
  }>;
9
- export declare function createMediaQuery({ min, max, customQuery }: Breakpoint, operator?: BreakpointEntry['operator']): string;
10
10
  //# sourceMappingURL=utils.d.ts.map
@@ -1,21 +1,57 @@
1
1
  import { stringAttributeDirective, observeMedia } from '@odx/foundation/utils';
2
2
  import { signal } from '@preact/signals-core';
3
+ import { k as keyBy, g as groupBy } from './vendor.js';
3
4
 
4
- const BreakpointHideTargetPlugin = (target, breakpoint) => {
5
- target.hidden = !breakpoint.matches;
6
- target.inert = !breakpoint.matches;
5
+ const BreakpointHideTargetPlugin = (target, change) => {
6
+ target.hidden = !change.matches;
7
+ target.inert = !change.matches;
7
8
  };
8
- const breakpointClassNameDirective = stringAttributeDirective("odx-breakpoint-class");
9
- const BreakpointClassNamePlugin = (target, breakpoint) => {
10
- if (!breakpointClassNameDirective.applied(target)) return;
11
- const classNames = breakpointClassNameDirective.value(target)?.split(" ") ?? [];
9
+ const BreakpointClassNamePlugin = (target, change) => {
10
+ const classNames = target.getAttribute("odx-breakpoint-class")?.split(" ") ?? [];
11
+ if (classNames.length === 0) return;
12
+ BreakpointHideTargetPlugin(target, { ...change, matches: true });
12
13
  for (const className of classNames) {
13
- target.classList.toggle(className, breakpoint.matches);
14
- target.hidden = false;
15
- target.inert = false;
14
+ target.classList.toggle(className, change.matches);
16
15
  }
17
16
  };
18
17
 
18
+ const operators = ["<", "<=", ">=", ">"];
19
+ const breakpointDirective = stringAttributeDirective("odx-breakpoint");
20
+ function buildBreakpoint(breakpoint, operator) {
21
+ const id = operator ? `${operator}${breakpoint.id}` : breakpoint.id;
22
+ let query = `(min-width: ${breakpoint.min}px) and (max-width: ${breakpoint.max}px)`;
23
+ switch (operator) {
24
+ case "<":
25
+ query = `(max-width: ${breakpoint.min - 0.02}px)`;
26
+ break;
27
+ case "<=":
28
+ query = `(max-width: ${breakpoint.max}px)`;
29
+ break;
30
+ case ">=":
31
+ query = `(min-width: ${breakpoint.min}px)`;
32
+ break;
33
+ case ">":
34
+ query = `(min-width: ${breakpoint.max + 0.02}px)`;
35
+ break;
36
+ }
37
+ query = [query, breakpoint.customQuery].filter(Boolean).join(" and ");
38
+ return { ...breakpoint, id, operator, query };
39
+ }
40
+ function createBreakpointHandler(plugins, targets) {
41
+ return (change) => {
42
+ for (const plugin of plugins) {
43
+ for (const target of targets) {
44
+ plugin(target, change);
45
+ }
46
+ }
47
+ };
48
+ }
49
+ function expandBreakpoints(...breakpoints) {
50
+ const expandBreakpoints2 = breakpoints.flatMap(
51
+ (breakpoint) => [void 0, ...operators].map((operator) => buildBreakpoint(breakpoint, operator))
52
+ );
53
+ return keyBy(expandBreakpoints2, (breakpoint) => breakpoint.id);
54
+ }
19
55
  function observeBreakpoint(breakpoint, initialValue = false) {
20
56
  let unobserveMedia;
21
57
  return signal(
@@ -25,72 +61,45 @@ function observeBreakpoint(breakpoint, initialValue = false) {
25
61
  unobserveMedia?.();
26
62
  },
27
63
  watched() {
28
- const query = breakpoint.query ?? createMediaQuery(breakpoint, breakpoint.operator);
29
- unobserveMedia = observeMedia(query, ({ matches }) => {
64
+ unobserveMedia = observeMedia(breakpoint.query, ({ matches }) => {
30
65
  this.value = { ...breakpoint, matches };
31
66
  });
32
67
  }
33
68
  }
34
69
  );
35
70
  }
36
- function createMediaQuery({ min, max, customQuery }, operator) {
37
- let mediaQuery = `(min-width: ${min}px) and (max-width: ${max}px)`;
38
- switch (operator) {
39
- case "<":
40
- mediaQuery = `(max-width: ${min - 0.02}px)`;
41
- break;
42
- case "<=":
43
- mediaQuery = `(max-width: ${max}px)`;
44
- break;
45
- case ">=":
46
- mediaQuery = `(min-width: ${min}px)`;
47
- break;
48
- case ">":
49
- mediaQuery = `(min-width: ${max + 0.02}px)`;
50
- break;
71
+
72
+ function unsubscribeAll(subscriptions) {
73
+ for (const unsubscribe of subscriptions) {
74
+ unsubscribe();
75
+ subscriptions.delete(unsubscribe);
51
76
  }
52
- return [mediaQuery, customQuery].filter(Boolean).join(" and ");
53
77
  }
54
-
55
- const breakpointRegistry = /* @__PURE__ */ new Map();
56
78
  const defaultBreakpoints = {
57
79
  mobile: { id: "mobile", min: 0, max: 575.98 },
58
80
  tablet: { id: "tablet", min: 576, max: 991.98 },
59
81
  desktop: { id: "desktop", min: 992, max: 1199.98 }
60
82
  };
61
- const BreakpointsConfig = (config) => ({
62
- breakpoints: [...Object.values(defaultBreakpoints), ...config?.breakpoints ?? []],
63
- plugins: [BreakpointHideTargetPlugin, BreakpointClassNamePlugin].concat(config?.plugins ?? [])
64
- });
65
- function setupBreakpoints(config = {}) {
66
- const { plugins, breakpoints } = BreakpointsConfig(config);
67
- for (const operator of [void 0, "<", "<=", ">=", ">"]) {
68
- for (const breakpoint of breakpoints) {
69
- const id = operator ? `${operator}${breakpoint.id}` : breakpoint.id;
70
- breakpointRegistry.set(id, { ...breakpoint, id, operator, query: createMediaQuery(breakpoint, operator) });
83
+ function setupBreakpoints(breakpointsConfig = [], root = document.documentElement) {
84
+ const breakpoints = expandBreakpoints(...Object.values(defaultBreakpoints), ...breakpointsConfig);
85
+ const plugins = [BreakpointHideTargetPlugin, BreakpointClassNamePlugin];
86
+ const subscriptions = /* @__PURE__ */ new Set();
87
+ const observer = new MutationObserver((mutations) => {
88
+ if (mutations.length === 0) return;
89
+ const breakpointDirectives = Array.from(document.querySelectorAll(breakpointDirective.selector));
90
+ unsubscribeAll(subscriptions);
91
+ const breakpointTargets = groupBy(breakpointDirectives, (host) => breakpointDirective.value(host) ?? "");
92
+ for (const [breakpointId, targets] of Object.entries(breakpointTargets)) {
93
+ const breakpoint = breakpoints[breakpointId];
94
+ if (!breakpoint) continue;
95
+ subscriptions.add(observeBreakpoint(breakpoint).subscribe(createBreakpointHandler(plugins, targets)));
71
96
  }
72
- }
73
- const breakpointDirective = stringAttributeDirective("odx-breakpoint");
74
- const subscriptions = Array.from(breakpointRegistry.values()).map((breakpoint) => {
75
- const breakpointSelector = `[${breakpointDirective.attribute}^="${breakpoint.id}"]`;
76
- return observeBreakpoint(breakpoint).subscribe((result) => {
77
- const breakpointDirectives = Array.from(document.querySelectorAll(breakpointSelector));
78
- if (!breakpointDirectives.length) return;
79
- for (const host of breakpointDirectives) {
80
- for (const plugin of plugins) {
81
- plugin(host, result);
82
- }
83
- }
84
- });
85
97
  });
98
+ observer.observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: [breakpointDirective.attribute] });
86
99
  return () => {
87
- for (const unsubscribe of subscriptions) {
88
- unsubscribe();
89
- }
100
+ unsubscribeAll(subscriptions);
101
+ observer.disconnect();
90
102
  };
91
103
  }
92
- function getBreakpoints() {
93
- return Array.from(breakpointRegistry.values()).filter((breakpoint) => !breakpoint.operator);
94
- }
95
104
 
96
- export { BreakpointClassNamePlugin, BreakpointHideTargetPlugin, BreakpointsConfig, setupBreakpoints as default, defaultBreakpoints, getBreakpoints };
105
+ export { BreakpointClassNamePlugin, BreakpointHideTargetPlugin, breakpointDirective, buildBreakpoint, createBreakpointHandler, setupBreakpoints as default, defaultBreakpoints, expandBreakpoints, observeBreakpoint };
@@ -3,7 +3,7 @@ import { CustomElement, customElement, CanBeExpanded, InteractiveControlElement,
3
3
  import { getUniqueId, toAriaBooleanAttribute, getAssignedElements, booleanAttributeDirective, optionalAttr, interactionResponse, getElementFromEvent, observeElementResize, unobserveElementResize, toPx, enableMotion, findClosestDocument, commandDirective, addGlobalEventListener, waitForAnimations, removeGlobalEventListener, getKeyInfo, clickedOutside, setFocusable, optionalSlot, parseDate, supportsHover, forwardEvent, isToggleOpen } from '@odx/foundation/utils';
4
4
  import { html, isServer, unsafeCSS, css, nothing } from 'lit';
5
5
  import { property, query, state } from 'lit/decorators.js';
6
- import { p as pick, R as RovingTabindexController, e, c as computePosition, o as offset, s as shift, f as flip, a as size, b as arrow, h as hide, d as autoUpdate, t as throttle, r as round, g as debounce } from './vendor.js';
6
+ import { p as pick, R as RovingTabindexController, e, c as computePosition, o as offset, s as shift, f as flip, a as size, b as arrow, h as hide, d as autoUpdate, t as throttle, r as round, i as debounce } from './vendor.js';
7
7
  import { when } from 'lit/directives/when.js';
8
8
  import { OdxIconElement } from '@odx/icons';
9
9
  import { IsLocalized } from '@odx/foundation/i18n';
@@ -0,0 +1,3 @@
1
+ export declare function observeDarkModeChange(callback: (enabled: boolean) => void): () => void;
2
+ export declare function isDarkModeEnabled(): boolean;
3
+ //# sourceMappingURL=dark-mode.d.ts.map
@@ -0,0 +1,2 @@
1
+ export * from './dark-mode.js';
2
+ //# sourceMappingURL=main.d.ts.map
package/dist/config.js ADDED
@@ -0,0 +1,23 @@
1
+ import { observeMedia } from '@odx/foundation/utils';
2
+ import { signal } from '@preact/signals-core';
3
+
4
+ let darkModeObserver;
5
+ const darkModeEnabled = signal(false, {
6
+ watched() {
7
+ darkModeObserver ??= observeDarkModeChange((enabled) => {
8
+ this.value = enabled;
9
+ });
10
+ },
11
+ unwatched() {
12
+ darkModeObserver?.();
13
+ darkModeObserver = void 0;
14
+ }
15
+ });
16
+ function observeDarkModeChange(callback) {
17
+ return observeMedia("(prefers-color-scheme: dark)", ({ matches }) => callback(matches));
18
+ }
19
+ function isDarkModeEnabled() {
20
+ return darkModeEnabled.value;
21
+ }
22
+
23
+ export { isDarkModeEnabled, observeDarkModeChange };
package/dist/i18n.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { signal, computed } from '@preact/signals-core';
2
- import { i as flattenObject, e } from './vendor.js';
2
+ import { j as flattenObject, e } from './vendor.js';
3
3
  import { parseDate } from '@odx/foundation/utils';
4
4
  import { _ as __decorateClass } from './_virtual_class-decorator-runtime.js';
5
5
  import 'lit/html.js';
package/dist/vendor.js CHANGED
@@ -3,6 +3,29 @@ import 'lit/html.js';
3
3
  import { directive } from 'lit/directive.js';
4
4
  import { AsyncDirective } from 'lit/async-directive.js';
5
5
 
6
+ function groupBy(arr, getKeyFromItem) {
7
+ const result = {};
8
+ for (let i = 0; i < arr.length; i++) {
9
+ const item = arr[i];
10
+ const key = getKeyFromItem(item);
11
+ if (!Object.hasOwn(result, key)) {
12
+ result[key] = [];
13
+ }
14
+ result[key].push(item);
15
+ }
16
+ return result;
17
+ }
18
+
19
+ function keyBy(arr, getKeyFromItem) {
20
+ const result = {};
21
+ for (let i = 0; i < arr.length; i++) {
22
+ const item = arr[i];
23
+ const key = getKeyFromItem(item);
24
+ result[key] = item;
25
+ }
26
+ return result;
27
+ }
28
+
6
29
  function minBy(items, getValue) {
7
30
  if (items.length === 0) {
8
31
  return undefined;
@@ -1965,4 +1988,4 @@ function round(value, precision = 0) {
1965
1988
  return Math.round(value * multiplier) / multiplier;
1966
1989
  }
1967
1990
 
1968
- export { RovingTabindexController as R, size as a, arrow as b, computePosition as c, autoUpdate as d, e, flip as f, debounce as g, hide as h, flattenObject as i, minBy as m, offset as o, pick as p, round as r, shift as s, throttle as t, uniqBy as u };
1991
+ export { RovingTabindexController as R, size as a, arrow as b, computePosition as c, autoUpdate as d, e, flip as f, groupBy as g, hide as h, debounce as i, flattenObject as j, keyBy as k, minBy as m, offset as o, pick as p, round as r, shift as s, throttle as t, uniqBy as u };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@odx/foundation",
3
3
  "displayName": "ODX Design System Foundation",
4
4
  "description": "A library of Web Component building blocks for ODX",
5
- "version": "1.0.0-beta.232",
5
+ "version": "1.0.0-beta.234",
6
6
  "author": "Drägerwerk AG & Co.KGaA",
7
7
  "license": "SEE LICENSE IN LICENSE",
8
8
  "homepage": "https://odx.draeger.com",
@@ -20,14 +20,14 @@
20
20
  "lit": "3.3.1"
21
21
  },
22
22
  "peerDependencies": {
23
- "@odx/icons": "^4.0.0-rc.47",
23
+ "@odx/icons": "^4.0.0-rc.49",
24
24
  "@odx/design-tokens": "^2.2.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@floating-ui/dom": "1.7.4",
28
28
  "@lit-labs/preact-signals": "1.0.3",
29
29
  "@lit-labs/rollup-plugin-minify-html-literals": "0.1.0",
30
- "@odx/icons": "4.0.0-rc.47",
30
+ "@odx/icons": "4.0.0-rc.49",
31
31
  "@spectrum-web-components/reactive-controllers": "1.8.0",
32
32
  "es-toolkit": "1.40.0",
33
33
  "sass-embedded": "1.93.2",
@@ -35,8 +35,8 @@
35
35
  "@odx-internal/config-stylelint": "0.0.0",
36
36
  "@odx-internal/config-typescript": "0.0.0",
37
37
  "@odx-internal/config-vite": "0.0.0",
38
- "@odx-internal/utils-storybook": "0.0.0",
39
- "@odx/design-tokens": "2.2.0"
38
+ "@odx/design-tokens": "2.2.0",
39
+ "@odx-internal/utils-storybook": "0.0.0"
40
40
  },
41
41
  "sideEffects": [
42
42
  "dist/components-loader.js",
@@ -53,6 +53,11 @@
53
53
  "types": "./dist/breakpoints/main.d.ts"
54
54
  },
55
55
  "./breakpoints/*": null,
56
+ "./config": {
57
+ "import": "./dist/config.js",
58
+ "types": "./dist/config/main.d.ts"
59
+ },
60
+ "./config/*": null,
56
61
  "./components": {
57
62
  "import": "./dist/components.js",
58
63
  "types": "./dist/components/main.d.ts"