@dloizides/ui-motion 1.2.0 → 1.3.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.
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { H as HairlineFigureProps } from '../constants-BrJ7VJYu.mjs';
3
- export { D as DEFAULT_HAIRLINE_INTENSITY, a as HAIRLINE_ASPECT_RATIO, b as HAIRLINE_TEST_ID, c as HairlineFigureName, d as HairlineVarName, e as HairlineVars, h as hairlineVars } from '../constants-BrJ7VJYu.mjs';
2
+ import { H as HairlineFigureProps } from '../constants-DXSyrmvQ.mjs';
3
+ export { D as DEFAULT_HAIRLINE_INTENSITY, a as HAIRLINE_ASPECT_RATIO, b as HAIRLINE_TEST_ID, c as HairlineFigureName, d as HairlineVarName, e as HairlineVars, h as hairlineVars } from '../constants-DXSyrmvQ.mjs';
4
4
  import '@dloizides/design-tokens';
5
5
 
6
6
  /** Mounts a hairline figure on the host View's DOM node (RN-web); destroyed on unmount. */
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { H as HairlineFigureProps } from '../constants-BrJ7VJYu.js';
3
- export { D as DEFAULT_HAIRLINE_INTENSITY, a as HAIRLINE_ASPECT_RATIO, b as HAIRLINE_TEST_ID, c as HairlineFigureName, d as HairlineVarName, e as HairlineVars, h as hairlineVars } from '../constants-BrJ7VJYu.js';
2
+ import { H as HairlineFigureProps } from '../constants-DXSyrmvQ.js';
3
+ export { D as DEFAULT_HAIRLINE_INTENSITY, a as HAIRLINE_ASPECT_RATIO, b as HAIRLINE_TEST_ID, c as HairlineFigureName, d as HairlineVarName, e as HairlineVars, h as hairlineVars } from '../constants-DXSyrmvQ.js';
4
4
  import '@dloizides/design-tokens';
5
5
 
6
6
  /** Mounts a hairline figure on the host View's DOM node (RN-web); destroyed on unmount. */
@@ -75,13 +75,23 @@ var FIGURE_REGISTRY = {
75
75
  ["vault" /* Vault */]: hairline.vault
76
76
  };
77
77
 
78
+ // src/hairline/HairlineVarName.ts
79
+ var HairlineVarName = /* @__PURE__ */ ((HairlineVarName2) => {
80
+ HairlineVarName2["Plate"] = "--hairline-plate";
81
+ HairlineVarName2["Hi"] = "--hairline-hi";
82
+ HairlineVarName2["Edge"] = "--hairline-edge";
83
+ HairlineVarName2["Mid"] = "--hairline-mid";
84
+ HairlineVarName2["Lo"] = "--hairline-lo";
85
+ return HairlineVarName2;
86
+ })(HairlineVarName || {});
87
+
78
88
  // src/hairline/utils/hairlineVars.ts
79
89
  var hairlineVars = (colors) => ({
80
- "--hairline-plate": colors.background,
81
- "--hairline-hi": colors.text,
82
- "--hairline-edge": colors.textSecondary,
83
- "--hairline-mid": colors.textTertiary !== void 0 ? colors.textTertiary : colors.border,
84
- "--hairline-lo": colors.divider
90
+ ["--hairline-plate" /* Plate */]: colors.background,
91
+ ["--hairline-hi" /* Hi */]: colors.text,
92
+ ["--hairline-edge" /* Edge */]: colors.textSecondary,
93
+ ["--hairline-mid" /* Mid */]: colors.textTertiary !== void 0 ? colors.textTertiary : colors.border,
94
+ ["--hairline-lo" /* Lo */]: colors.divider
85
95
  });
86
96
  var styles = reactNative.StyleSheet.create({
87
97
  host: { width: "100%", aspectRatio: HAIRLINE_ASPECT_RATIO }
@@ -126,6 +136,7 @@ exports.HAIRLINE_ASPECT_RATIO = HAIRLINE_ASPECT_RATIO;
126
136
  exports.HAIRLINE_TEST_ID = HAIRLINE_TEST_ID;
127
137
  exports.HairlineFigure = HairlineFigure;
128
138
  exports.HairlineFigureName = HairlineFigureName;
139
+ exports.HairlineVarName = HairlineVarName;
129
140
  exports.hairlineVars = hairlineVars;
130
141
  //# sourceMappingURL=web.js.map
131
142
  //# sourceMappingURL=web.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hairline/constants.ts","../../src/hairline/HairlineFigureName.ts","../../src/hairline/data/figureRegistry.ts","../../src/hairline/utils/hairlineVars.ts","../../src/hairline/components/HairlineFigure.web.tsx"],"names":["HairlineFigureName","basket","branches","cabinet","dish","drawer","elevator","exploded","keyboard","laptop","lockers","loupe","padlock","patch","phone","phosphor","plot","plug","query","rail","riffle","router","sieve","slow","terminal","terrain","turntable","vault","StyleSheet","useRef","useEffect","View"],"mappings":"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","file":"web.js","sourcesContent":["export const HAIRLINE_TEST_ID = 'motion-hairline-figure';\nexport const HAIRLINE_ASPECT_RATIO = 5 / 4;\nexport const DEFAULT_HAIRLINE_INTENSITY = 0.5;\n","export const enum HairlineFigureName {\n Basket = 'basket',\n Branches = 'branches',\n Cabinet = 'cabinet',\n Dish = 'dish',\n Drawer = 'drawer',\n Elevator = 'elevator',\n Exploded = 'exploded',\n Keyboard = 'keyboard',\n Laptop = 'laptop',\n Lockers = 'lockers',\n Loupe = 'loupe',\n Padlock = 'padlock',\n Patch = 'patch',\n Phone = 'phone',\n Phosphor = 'phosphor',\n Plot = 'plot',\n Plug = 'plug',\n Query = 'query',\n Rail = 'rail',\n Riffle = 'riffle',\n Router = 'router',\n Sieve = 'sieve',\n Slow = 'slow',\n Terminal = 'terminal',\n Terrain = 'terrain',\n Turntable = 'turntable',\n Vault = 'vault',\n}\n","import {\n basket, branches, cabinet, dish, drawer, elevator, exploded, keyboard, laptop,\n lockers, loupe, padlock, patch, phone, phosphor, plot, plug, query, rail,\n riffle, router, sieve, slow, terminal, terrain, turntable, vault,\n type Figure, type HairlineOptions,\n} from '@lucasmarkes/hairline';\n\nimport { HairlineFigureName } from '../HairlineFigureName';\n\nexport type MountFigure = (el: HTMLElement, options?: HairlineOptions) => Figure;\n\nexport const FIGURE_REGISTRY: Record<HairlineFigureName, MountFigure> = {\n [HairlineFigureName.Basket]: basket,\n [HairlineFigureName.Branches]: branches,\n [HairlineFigureName.Cabinet]: cabinet,\n [HairlineFigureName.Dish]: dish,\n [HairlineFigureName.Drawer]: drawer,\n [HairlineFigureName.Elevator]: elevator,\n [HairlineFigureName.Exploded]: exploded,\n [HairlineFigureName.Keyboard]: keyboard,\n [HairlineFigureName.Laptop]: laptop,\n [HairlineFigureName.Lockers]: lockers,\n [HairlineFigureName.Loupe]: loupe,\n [HairlineFigureName.Padlock]: padlock,\n [HairlineFigureName.Patch]: patch,\n [HairlineFigureName.Phone]: phone,\n [HairlineFigureName.Phosphor]: phosphor,\n [HairlineFigureName.Plot]: plot,\n [HairlineFigureName.Plug]: plug,\n [HairlineFigureName.Query]: query,\n [HairlineFigureName.Rail]: rail,\n [HairlineFigureName.Riffle]: riffle,\n [HairlineFigureName.Router]: router,\n [HairlineFigureName.Sieve]: sieve,\n [HairlineFigureName.Slow]: slow,\n [HairlineFigureName.Terminal]: terminal,\n [HairlineFigureName.Terrain]: terrain,\n [HairlineFigureName.Turntable]: turntable,\n [HairlineFigureName.Vault]: vault,\n};\n","import type { ModeColors } from '@dloizides/design-tokens';\n\nimport type { HairlineVars } from '../types';\n\n/** Maps one theme mode's colour tokens onto the hairline palette vars (stroke width stays upstream). */\nexport const hairlineVars = (colors: ModeColors): HairlineVars => ({\n '--hairline-plate': colors.background,\n '--hairline-hi': colors.text,\n '--hairline-edge': colors.textSecondary,\n '--hairline-mid': colors.textTertiary !== undefined ? colors.textTertiary : colors.border,\n '--hairline-lo': colors.divider,\n});\n","import React, { useEffect, useRef } from 'react';\n\nimport { StyleSheet, View } from 'react-native';\n\nimport type { Figure } from '@lucasmarkes/hairline';\n\nimport { DEFAULT_HAIRLINE_INTENSITY, HAIRLINE_ASPECT_RATIO, HAIRLINE_TEST_ID } from '../constants';\nimport { FIGURE_REGISTRY } from '../data/figureRegistry';\nimport type { HairlineFigureProps } from '../types';\nimport { hairlineVars } from '../utils/hairlineVars';\n\nconst styles = StyleSheet.create({\n host: { width: '100%', aspectRatio: HAIRLINE_ASPECT_RATIO },\n});\n\nconst toElement = (view: View | null): HTMLElement | null => view as unknown as HTMLElement | null;\n\n/** Mounts a hairline figure on the host View's DOM node (RN-web); destroyed on unmount. */\nexport const HairlineFigure = ({\n figure,\n colors,\n intensity = DEFAULT_HAIRLINE_INTENSITY,\n label,\n testID = HAIRLINE_TEST_ID,\n}: HairlineFigureProps): React.ReactElement => {\n const hostRef = useRef<View>(null);\n const figureRef = useRef<Figure | null>(null);\n const optionsRef = useRef({ intensity, label });\n optionsRef.current = { intensity, label };\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const vars = Object.entries(hairlineVars(colors));\n vars.forEach(([name, value]) => el.style.setProperty(name, value));\n return () => vars.forEach(([name]) => el.style.removeProperty(name));\n }, [colors]);\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const mounted = FIGURE_REGISTRY[figure](el, optionsRef.current);\n figureRef.current = mounted;\n return () => {\n mounted.destroy();\n figureRef.current = null;\n };\n }, [figure]);\n\n useEffect(() => {\n figureRef.current?.update({ intensity, label });\n }, [intensity, label]);\n\n return <View ref={hostRef} style={styles.host} testID={testID} />;\n};\n"]}
1
+ {"version":3,"sources":["../../src/hairline/constants.ts","../../src/hairline/HairlineFigureName.ts","../../src/hairline/data/figureRegistry.ts","../../src/hairline/HairlineVarName.ts","../../src/hairline/utils/hairlineVars.ts","../../src/hairline/components/HairlineFigure.web.tsx"],"names":["HairlineFigureName","basket","branches","cabinet","dish","drawer","elevator","exploded","keyboard","laptop","lockers","loupe","padlock","patch","phone","phosphor","plot","plug","query","rail","riffle","router","sieve","slow","terminal","terrain","turntable","vault","HairlineVarName","StyleSheet","useRef","useEffect","View"],"mappings":"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","file":"web.js","sourcesContent":["export const HAIRLINE_TEST_ID = 'motion-hairline-figure';\nexport const HAIRLINE_ASPECT_RATIO = 5 / 4;\nexport const DEFAULT_HAIRLINE_INTENSITY = 0.5;\nexport const HAIRLINE_HANDLE_GLOBAL = '__dloizidesHairline';\n","export const enum HairlineFigureName {\n Basket = 'basket',\n Branches = 'branches',\n Cabinet = 'cabinet',\n Dish = 'dish',\n Drawer = 'drawer',\n Elevator = 'elevator',\n Exploded = 'exploded',\n Keyboard = 'keyboard',\n Laptop = 'laptop',\n Lockers = 'lockers',\n Loupe = 'loupe',\n Padlock = 'padlock',\n Patch = 'patch',\n Phone = 'phone',\n Phosphor = 'phosphor',\n Plot = 'plot',\n Plug = 'plug',\n Query = 'query',\n Rail = 'rail',\n Riffle = 'riffle',\n Router = 'router',\n Sieve = 'sieve',\n Slow = 'slow',\n Terminal = 'terminal',\n Terrain = 'terrain',\n Turntable = 'turntable',\n Vault = 'vault',\n}\n","import {\n basket, branches, cabinet, dish, drawer, elevator, exploded, keyboard, laptop,\n lockers, loupe, padlock, patch, phone, phosphor, plot, plug, query, rail,\n riffle, router, sieve, slow, terminal, terrain, turntable, vault,\n type Figure, type HairlineOptions,\n} from '@lucasmarkes/hairline';\n\nimport { HairlineFigureName } from '../HairlineFigureName';\n\nexport type MountFigure = (el: HTMLElement, options?: HairlineOptions) => Figure;\n\nexport const FIGURE_REGISTRY: Record<HairlineFigureName, MountFigure> = {\n [HairlineFigureName.Basket]: basket,\n [HairlineFigureName.Branches]: branches,\n [HairlineFigureName.Cabinet]: cabinet,\n [HairlineFigureName.Dish]: dish,\n [HairlineFigureName.Drawer]: drawer,\n [HairlineFigureName.Elevator]: elevator,\n [HairlineFigureName.Exploded]: exploded,\n [HairlineFigureName.Keyboard]: keyboard,\n [HairlineFigureName.Laptop]: laptop,\n [HairlineFigureName.Lockers]: lockers,\n [HairlineFigureName.Loupe]: loupe,\n [HairlineFigureName.Padlock]: padlock,\n [HairlineFigureName.Patch]: patch,\n [HairlineFigureName.Phone]: phone,\n [HairlineFigureName.Phosphor]: phosphor,\n [HairlineFigureName.Plot]: plot,\n [HairlineFigureName.Plug]: plug,\n [HairlineFigureName.Query]: query,\n [HairlineFigureName.Rail]: rail,\n [HairlineFigureName.Riffle]: riffle,\n [HairlineFigureName.Router]: router,\n [HairlineFigureName.Sieve]: sieve,\n [HairlineFigureName.Slow]: slow,\n [HairlineFigureName.Terminal]: terminal,\n [HairlineFigureName.Terrain]: terrain,\n [HairlineFigureName.Turntable]: turntable,\n [HairlineFigureName.Vault]: vault,\n};\n","export const enum HairlineVarName {\n Plate = '--hairline-plate',\n Hi = '--hairline-hi',\n Edge = '--hairline-edge',\n Mid = '--hairline-mid',\n Lo = '--hairline-lo',\n}\n","import type { ModeColors } from '@dloizides/design-tokens';\n\nimport { HairlineVarName } from '../HairlineVarName';\nimport type { HairlineVars } from '../types';\n\n/** Maps one theme mode's colour tokens onto the hairline palette vars (stroke width stays upstream). */\nexport const hairlineVars = (colors: ModeColors): HairlineVars => ({\n [HairlineVarName.Plate]: colors.background,\n [HairlineVarName.Hi]: colors.text,\n [HairlineVarName.Edge]: colors.textSecondary,\n [HairlineVarName.Mid]: colors.textTertiary !== undefined ? colors.textTertiary : colors.border,\n [HairlineVarName.Lo]: colors.divider,\n});\n","import React, { useEffect, useRef } from 'react';\n\nimport { StyleSheet, View } from 'react-native';\n\nimport type { Figure } from '@lucasmarkes/hairline';\n\nimport { DEFAULT_HAIRLINE_INTENSITY, HAIRLINE_ASPECT_RATIO, HAIRLINE_TEST_ID } from '../constants';\nimport { FIGURE_REGISTRY } from '../data/figureRegistry';\nimport type { HairlineFigureProps } from '../types';\nimport { hairlineVars } from '../utils/hairlineVars';\n\nconst styles = StyleSheet.create({\n host: { width: '100%', aspectRatio: HAIRLINE_ASPECT_RATIO },\n});\n\nconst toElement = (view: View | null): HTMLElement | null => view as unknown as HTMLElement | null;\n\n/** Mounts a hairline figure on the host View's DOM node (RN-web); destroyed on unmount. */\nexport const HairlineFigure = ({\n figure,\n colors,\n intensity = DEFAULT_HAIRLINE_INTENSITY,\n label,\n testID = HAIRLINE_TEST_ID,\n}: HairlineFigureProps): React.ReactElement => {\n const hostRef = useRef<View>(null);\n const figureRef = useRef<Figure | null>(null);\n const optionsRef = useRef({ intensity, label });\n optionsRef.current = { intensity, label };\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const vars = Object.entries(hairlineVars(colors));\n vars.forEach(([name, value]) => el.style.setProperty(name, value));\n return () => vars.forEach(([name]) => el.style.removeProperty(name));\n }, [colors]);\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const mounted = FIGURE_REGISTRY[figure](el, optionsRef.current);\n figureRef.current = mounted;\n return () => {\n mounted.destroy();\n figureRef.current = null;\n };\n }, [figure]);\n\n useEffect(() => {\n figureRef.current?.update({ intensity, label });\n }, [intensity, label]);\n\n return <View ref={hostRef} style={styles.host} testID={testID} />;\n};\n"]}
@@ -73,13 +73,23 @@ var FIGURE_REGISTRY = {
73
73
  ["vault" /* Vault */]: vault
74
74
  };
75
75
 
76
+ // src/hairline/HairlineVarName.ts
77
+ var HairlineVarName = /* @__PURE__ */ ((HairlineVarName2) => {
78
+ HairlineVarName2["Plate"] = "--hairline-plate";
79
+ HairlineVarName2["Hi"] = "--hairline-hi";
80
+ HairlineVarName2["Edge"] = "--hairline-edge";
81
+ HairlineVarName2["Mid"] = "--hairline-mid";
82
+ HairlineVarName2["Lo"] = "--hairline-lo";
83
+ return HairlineVarName2;
84
+ })(HairlineVarName || {});
85
+
76
86
  // src/hairline/utils/hairlineVars.ts
77
87
  var hairlineVars = (colors) => ({
78
- "--hairline-plate": colors.background,
79
- "--hairline-hi": colors.text,
80
- "--hairline-edge": colors.textSecondary,
81
- "--hairline-mid": colors.textTertiary !== void 0 ? colors.textTertiary : colors.border,
82
- "--hairline-lo": colors.divider
88
+ ["--hairline-plate" /* Plate */]: colors.background,
89
+ ["--hairline-hi" /* Hi */]: colors.text,
90
+ ["--hairline-edge" /* Edge */]: colors.textSecondary,
91
+ ["--hairline-mid" /* Mid */]: colors.textTertiary !== void 0 ? colors.textTertiary : colors.border,
92
+ ["--hairline-lo" /* Lo */]: colors.divider
83
93
  });
84
94
  var styles = StyleSheet.create({
85
95
  host: { width: "100%", aspectRatio: HAIRLINE_ASPECT_RATIO }
@@ -119,6 +129,6 @@ var HairlineFigure = ({
119
129
  return /* @__PURE__ */ jsx(View, { ref: hostRef, style: styles.host, testID });
120
130
  };
121
131
 
122
- export { DEFAULT_HAIRLINE_INTENSITY, HAIRLINE_ASPECT_RATIO, HAIRLINE_TEST_ID, HairlineFigure, HairlineFigureName, hairlineVars };
132
+ export { DEFAULT_HAIRLINE_INTENSITY, HAIRLINE_ASPECT_RATIO, HAIRLINE_TEST_ID, HairlineFigure, HairlineFigureName, HairlineVarName, hairlineVars };
123
133
  //# sourceMappingURL=web.mjs.map
124
134
  //# sourceMappingURL=web.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hairline/constants.ts","../../src/hairline/HairlineFigureName.ts","../../src/hairline/data/figureRegistry.ts","../../src/hairline/utils/hairlineVars.ts","../../src/hairline/components/HairlineFigure.web.tsx"],"names":["HairlineFigureName"],"mappings":"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","file":"web.mjs","sourcesContent":["export const HAIRLINE_TEST_ID = 'motion-hairline-figure';\nexport const HAIRLINE_ASPECT_RATIO = 5 / 4;\nexport const DEFAULT_HAIRLINE_INTENSITY = 0.5;\n","export const enum HairlineFigureName {\n Basket = 'basket',\n Branches = 'branches',\n Cabinet = 'cabinet',\n Dish = 'dish',\n Drawer = 'drawer',\n Elevator = 'elevator',\n Exploded = 'exploded',\n Keyboard = 'keyboard',\n Laptop = 'laptop',\n Lockers = 'lockers',\n Loupe = 'loupe',\n Padlock = 'padlock',\n Patch = 'patch',\n Phone = 'phone',\n Phosphor = 'phosphor',\n Plot = 'plot',\n Plug = 'plug',\n Query = 'query',\n Rail = 'rail',\n Riffle = 'riffle',\n Router = 'router',\n Sieve = 'sieve',\n Slow = 'slow',\n Terminal = 'terminal',\n Terrain = 'terrain',\n Turntable = 'turntable',\n Vault = 'vault',\n}\n","import {\n basket, branches, cabinet, dish, drawer, elevator, exploded, keyboard, laptop,\n lockers, loupe, padlock, patch, phone, phosphor, plot, plug, query, rail,\n riffle, router, sieve, slow, terminal, terrain, turntable, vault,\n type Figure, type HairlineOptions,\n} from '@lucasmarkes/hairline';\n\nimport { HairlineFigureName } from '../HairlineFigureName';\n\nexport type MountFigure = (el: HTMLElement, options?: HairlineOptions) => Figure;\n\nexport const FIGURE_REGISTRY: Record<HairlineFigureName, MountFigure> = {\n [HairlineFigureName.Basket]: basket,\n [HairlineFigureName.Branches]: branches,\n [HairlineFigureName.Cabinet]: cabinet,\n [HairlineFigureName.Dish]: dish,\n [HairlineFigureName.Drawer]: drawer,\n [HairlineFigureName.Elevator]: elevator,\n [HairlineFigureName.Exploded]: exploded,\n [HairlineFigureName.Keyboard]: keyboard,\n [HairlineFigureName.Laptop]: laptop,\n [HairlineFigureName.Lockers]: lockers,\n [HairlineFigureName.Loupe]: loupe,\n [HairlineFigureName.Padlock]: padlock,\n [HairlineFigureName.Patch]: patch,\n [HairlineFigureName.Phone]: phone,\n [HairlineFigureName.Phosphor]: phosphor,\n [HairlineFigureName.Plot]: plot,\n [HairlineFigureName.Plug]: plug,\n [HairlineFigureName.Query]: query,\n [HairlineFigureName.Rail]: rail,\n [HairlineFigureName.Riffle]: riffle,\n [HairlineFigureName.Router]: router,\n [HairlineFigureName.Sieve]: sieve,\n [HairlineFigureName.Slow]: slow,\n [HairlineFigureName.Terminal]: terminal,\n [HairlineFigureName.Terrain]: terrain,\n [HairlineFigureName.Turntable]: turntable,\n [HairlineFigureName.Vault]: vault,\n};\n","import type { ModeColors } from '@dloizides/design-tokens';\n\nimport type { HairlineVars } from '../types';\n\n/** Maps one theme mode's colour tokens onto the hairline palette vars (stroke width stays upstream). */\nexport const hairlineVars = (colors: ModeColors): HairlineVars => ({\n '--hairline-plate': colors.background,\n '--hairline-hi': colors.text,\n '--hairline-edge': colors.textSecondary,\n '--hairline-mid': colors.textTertiary !== undefined ? colors.textTertiary : colors.border,\n '--hairline-lo': colors.divider,\n});\n","import React, { useEffect, useRef } from 'react';\n\nimport { StyleSheet, View } from 'react-native';\n\nimport type { Figure } from '@lucasmarkes/hairline';\n\nimport { DEFAULT_HAIRLINE_INTENSITY, HAIRLINE_ASPECT_RATIO, HAIRLINE_TEST_ID } from '../constants';\nimport { FIGURE_REGISTRY } from '../data/figureRegistry';\nimport type { HairlineFigureProps } from '../types';\nimport { hairlineVars } from '../utils/hairlineVars';\n\nconst styles = StyleSheet.create({\n host: { width: '100%', aspectRatio: HAIRLINE_ASPECT_RATIO },\n});\n\nconst toElement = (view: View | null): HTMLElement | null => view as unknown as HTMLElement | null;\n\n/** Mounts a hairline figure on the host View's DOM node (RN-web); destroyed on unmount. */\nexport const HairlineFigure = ({\n figure,\n colors,\n intensity = DEFAULT_HAIRLINE_INTENSITY,\n label,\n testID = HAIRLINE_TEST_ID,\n}: HairlineFigureProps): React.ReactElement => {\n const hostRef = useRef<View>(null);\n const figureRef = useRef<Figure | null>(null);\n const optionsRef = useRef({ intensity, label });\n optionsRef.current = { intensity, label };\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const vars = Object.entries(hairlineVars(colors));\n vars.forEach(([name, value]) => el.style.setProperty(name, value));\n return () => vars.forEach(([name]) => el.style.removeProperty(name));\n }, [colors]);\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const mounted = FIGURE_REGISTRY[figure](el, optionsRef.current);\n figureRef.current = mounted;\n return () => {\n mounted.destroy();\n figureRef.current = null;\n };\n }, [figure]);\n\n useEffect(() => {\n figureRef.current?.update({ intensity, label });\n }, [intensity, label]);\n\n return <View ref={hostRef} style={styles.host} testID={testID} />;\n};\n"]}
1
+ {"version":3,"sources":["../../src/hairline/constants.ts","../../src/hairline/HairlineFigureName.ts","../../src/hairline/data/figureRegistry.ts","../../src/hairline/HairlineVarName.ts","../../src/hairline/utils/hairlineVars.ts","../../src/hairline/components/HairlineFigure.web.tsx"],"names":["HairlineFigureName","HairlineVarName"],"mappings":"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","file":"web.mjs","sourcesContent":["export const HAIRLINE_TEST_ID = 'motion-hairline-figure';\nexport const HAIRLINE_ASPECT_RATIO = 5 / 4;\nexport const DEFAULT_HAIRLINE_INTENSITY = 0.5;\nexport const HAIRLINE_HANDLE_GLOBAL = '__dloizidesHairline';\n","export const enum HairlineFigureName {\n Basket = 'basket',\n Branches = 'branches',\n Cabinet = 'cabinet',\n Dish = 'dish',\n Drawer = 'drawer',\n Elevator = 'elevator',\n Exploded = 'exploded',\n Keyboard = 'keyboard',\n Laptop = 'laptop',\n Lockers = 'lockers',\n Loupe = 'loupe',\n Padlock = 'padlock',\n Patch = 'patch',\n Phone = 'phone',\n Phosphor = 'phosphor',\n Plot = 'plot',\n Plug = 'plug',\n Query = 'query',\n Rail = 'rail',\n Riffle = 'riffle',\n Router = 'router',\n Sieve = 'sieve',\n Slow = 'slow',\n Terminal = 'terminal',\n Terrain = 'terrain',\n Turntable = 'turntable',\n Vault = 'vault',\n}\n","import {\n basket, branches, cabinet, dish, drawer, elevator, exploded, keyboard, laptop,\n lockers, loupe, padlock, patch, phone, phosphor, plot, plug, query, rail,\n riffle, router, sieve, slow, terminal, terrain, turntable, vault,\n type Figure, type HairlineOptions,\n} from '@lucasmarkes/hairline';\n\nimport { HairlineFigureName } from '../HairlineFigureName';\n\nexport type MountFigure = (el: HTMLElement, options?: HairlineOptions) => Figure;\n\nexport const FIGURE_REGISTRY: Record<HairlineFigureName, MountFigure> = {\n [HairlineFigureName.Basket]: basket,\n [HairlineFigureName.Branches]: branches,\n [HairlineFigureName.Cabinet]: cabinet,\n [HairlineFigureName.Dish]: dish,\n [HairlineFigureName.Drawer]: drawer,\n [HairlineFigureName.Elevator]: elevator,\n [HairlineFigureName.Exploded]: exploded,\n [HairlineFigureName.Keyboard]: keyboard,\n [HairlineFigureName.Laptop]: laptop,\n [HairlineFigureName.Lockers]: lockers,\n [HairlineFigureName.Loupe]: loupe,\n [HairlineFigureName.Padlock]: padlock,\n [HairlineFigureName.Patch]: patch,\n [HairlineFigureName.Phone]: phone,\n [HairlineFigureName.Phosphor]: phosphor,\n [HairlineFigureName.Plot]: plot,\n [HairlineFigureName.Plug]: plug,\n [HairlineFigureName.Query]: query,\n [HairlineFigureName.Rail]: rail,\n [HairlineFigureName.Riffle]: riffle,\n [HairlineFigureName.Router]: router,\n [HairlineFigureName.Sieve]: sieve,\n [HairlineFigureName.Slow]: slow,\n [HairlineFigureName.Terminal]: terminal,\n [HairlineFigureName.Terrain]: terrain,\n [HairlineFigureName.Turntable]: turntable,\n [HairlineFigureName.Vault]: vault,\n};\n","export const enum HairlineVarName {\n Plate = '--hairline-plate',\n Hi = '--hairline-hi',\n Edge = '--hairline-edge',\n Mid = '--hairline-mid',\n Lo = '--hairline-lo',\n}\n","import type { ModeColors } from '@dloizides/design-tokens';\n\nimport { HairlineVarName } from '../HairlineVarName';\nimport type { HairlineVars } from '../types';\n\n/** Maps one theme mode's colour tokens onto the hairline palette vars (stroke width stays upstream). */\nexport const hairlineVars = (colors: ModeColors): HairlineVars => ({\n [HairlineVarName.Plate]: colors.background,\n [HairlineVarName.Hi]: colors.text,\n [HairlineVarName.Edge]: colors.textSecondary,\n [HairlineVarName.Mid]: colors.textTertiary !== undefined ? colors.textTertiary : colors.border,\n [HairlineVarName.Lo]: colors.divider,\n});\n","import React, { useEffect, useRef } from 'react';\n\nimport { StyleSheet, View } from 'react-native';\n\nimport type { Figure } from '@lucasmarkes/hairline';\n\nimport { DEFAULT_HAIRLINE_INTENSITY, HAIRLINE_ASPECT_RATIO, HAIRLINE_TEST_ID } from '../constants';\nimport { FIGURE_REGISTRY } from '../data/figureRegistry';\nimport type { HairlineFigureProps } from '../types';\nimport { hairlineVars } from '../utils/hairlineVars';\n\nconst styles = StyleSheet.create({\n host: { width: '100%', aspectRatio: HAIRLINE_ASPECT_RATIO },\n});\n\nconst toElement = (view: View | null): HTMLElement | null => view as unknown as HTMLElement | null;\n\n/** Mounts a hairline figure on the host View's DOM node (RN-web); destroyed on unmount. */\nexport const HairlineFigure = ({\n figure,\n colors,\n intensity = DEFAULT_HAIRLINE_INTENSITY,\n label,\n testID = HAIRLINE_TEST_ID,\n}: HairlineFigureProps): React.ReactElement => {\n const hostRef = useRef<View>(null);\n const figureRef = useRef<Figure | null>(null);\n const optionsRef = useRef({ intensity, label });\n optionsRef.current = { intensity, label };\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const vars = Object.entries(hairlineVars(colors));\n vars.forEach(([name, value]) => el.style.setProperty(name, value));\n return () => vars.forEach(([name]) => el.style.removeProperty(name));\n }, [colors]);\n\n useEffect(() => {\n const el = toElement(hostRef.current);\n if (el === null) return undefined;\n const mounted = FIGURE_REGISTRY[figure](el, optionsRef.current);\n figureRef.current = mounted;\n return () => {\n mounted.destroy();\n figureRef.current = null;\n };\n }, [figure]);\n\n useEffect(() => {\n figureRef.current?.update({ intensity, label });\n }, [intensity, label]);\n\n return <View ref={hostRef} style={styles.host} testID={testID} />;\n};\n"]}
@@ -0,0 +1,44 @@
1
+ import { MotionDurations, MotionEasings } from '@dloizides/design-tokens';
2
+
3
+ type LogoDurationToken = keyof MotionDurations;
4
+ type LogoEasingToken = keyof MotionEasings;
5
+ /** One beat: animate every `[data-motion-layer="<layer>"]` node through `keyframes`. */
6
+ interface LogoBeat {
7
+ layer: string;
8
+ keyframes: Keyframe[];
9
+ duration: LogoDurationToken | number;
10
+ easing?: LogoEasingToken;
11
+ delay?: number;
12
+ }
13
+ type LogoTimeline = readonly LogoBeat[];
14
+ interface PlayLogoOptions {
15
+ reducedMotion?: boolean;
16
+ iterations?: number;
17
+ }
18
+ interface LogoPlayback {
19
+ finished: Promise<void>;
20
+ cancel: () => void;
21
+ }
22
+ type BindMicroOptions = Pick<PlayLogoOptions, 'reducedMotion'>;
23
+
24
+ /** Plays a logo timeline on the mark's `data-motion-layer` nodes via the Web Animations API. */
25
+ declare function playLogo(svg: Element, timeline: LogoTimeline, options?: PlayLogoOptions): LogoPlayback;
26
+
27
+ /** What starts a logo micro-animation bound with `bindMicro`. */
28
+ declare const enum MicroTrigger {
29
+ Hover = "hover",
30
+ Focus = "focus",
31
+ Loading = "loading"
32
+ }
33
+
34
+ /** Binds a micro-animation to hover, focus or loading; returns the unbind function. */
35
+ declare function bindMicro(svg: Element, timeline: LogoTimeline, trigger: MicroTrigger | `${MicroTrigger}`, options?: BindMicroOptions): () => void;
36
+
37
+ /** A duration token (`fast`, `base`, `slow`, `instant`) to ms; a number passes through. */
38
+ declare function resolveDuration(duration: LogoDurationToken | number): number;
39
+ /** An easing token to its css timing function; no token means `standard`. */
40
+ declare function resolveEasing(easing: LogoEasingToken | undefined): string;
41
+
42
+ declare const MOTION_LAYER_ATTRIBUTE = "data-motion-layer";
43
+
44
+ export { type BindMicroOptions, type LogoBeat, type LogoDurationToken, type LogoEasingToken, type LogoPlayback, type LogoTimeline, MOTION_LAYER_ATTRIBUTE, MicroTrigger, type PlayLogoOptions, bindMicro, playLogo, resolveDuration, resolveEasing };
@@ -0,0 +1,44 @@
1
+ import { MotionDurations, MotionEasings } from '@dloizides/design-tokens';
2
+
3
+ type LogoDurationToken = keyof MotionDurations;
4
+ type LogoEasingToken = keyof MotionEasings;
5
+ /** One beat: animate every `[data-motion-layer="<layer>"]` node through `keyframes`. */
6
+ interface LogoBeat {
7
+ layer: string;
8
+ keyframes: Keyframe[];
9
+ duration: LogoDurationToken | number;
10
+ easing?: LogoEasingToken;
11
+ delay?: number;
12
+ }
13
+ type LogoTimeline = readonly LogoBeat[];
14
+ interface PlayLogoOptions {
15
+ reducedMotion?: boolean;
16
+ iterations?: number;
17
+ }
18
+ interface LogoPlayback {
19
+ finished: Promise<void>;
20
+ cancel: () => void;
21
+ }
22
+ type BindMicroOptions = Pick<PlayLogoOptions, 'reducedMotion'>;
23
+
24
+ /** Plays a logo timeline on the mark's `data-motion-layer` nodes via the Web Animations API. */
25
+ declare function playLogo(svg: Element, timeline: LogoTimeline, options?: PlayLogoOptions): LogoPlayback;
26
+
27
+ /** What starts a logo micro-animation bound with `bindMicro`. */
28
+ declare const enum MicroTrigger {
29
+ Hover = "hover",
30
+ Focus = "focus",
31
+ Loading = "loading"
32
+ }
33
+
34
+ /** Binds a micro-animation to hover, focus or loading; returns the unbind function. */
35
+ declare function bindMicro(svg: Element, timeline: LogoTimeline, trigger: MicroTrigger | `${MicroTrigger}`, options?: BindMicroOptions): () => void;
36
+
37
+ /** A duration token (`fast`, `base`, `slow`, `instant`) to ms; a number passes through. */
38
+ declare function resolveDuration(duration: LogoDurationToken | number): number;
39
+ /** An easing token to its css timing function; no token means `standard`. */
40
+ declare function resolveEasing(easing: LogoEasingToken | undefined): string;
41
+
42
+ declare const MOTION_LAYER_ATTRIBUTE = "data-motion-layer";
43
+
44
+ export { type BindMicroOptions, type LogoBeat, type LogoDurationToken, type LogoEasingToken, type LogoPlayback, type LogoTimeline, MOTION_LAYER_ATTRIBUTE, MicroTrigger, type PlayLogoOptions, bindMicro, playLogo, resolveDuration, resolveEasing };
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ var designTokens = require('@dloizides/design-tokens');
4
+
5
+ // src/logo/constants.ts
6
+ var MOTION_LAYER_ATTRIBUTE = "data-motion-layer";
7
+ var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
8
+ var DEFAULT_LOGO_EASING = "standard";
9
+
10
+ // src/logo/utils/layers.ts
11
+ var FRAME_META_KEYS = /* @__PURE__ */ new Set(["offset", "easing", "composite"]);
12
+ function findLayers(root, layer) {
13
+ const selector = `[${MOTION_LAYER_ATTRIBUTE}=${JSON.stringify(layer)}]`;
14
+ const nodes = Array.from(root.querySelectorAll(selector));
15
+ if (root.matches(selector)) nodes.unshift(root);
16
+ return nodes.filter((node) => "style" in node);
17
+ }
18
+ function applyFinalFrame(element, keyframes) {
19
+ const last = keyframes[keyframes.length - 1];
20
+ if (last === void 0) return;
21
+ const style = element.style;
22
+ Object.entries(last).filter(([key, value]) => !FRAME_META_KEYS.has(key) && value !== null && value !== void 0).forEach(([key, value]) => {
23
+ style[key] = String(value);
24
+ });
25
+ }
26
+ function supportsWebAnimations(element) {
27
+ return typeof element.animate === "function";
28
+ }
29
+ function prefersReducedMotion() {
30
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
31
+ return window.matchMedia(REDUCED_MOTION_QUERY).matches;
32
+ }
33
+ function resolveDuration(duration) {
34
+ if (typeof duration === "number") return duration;
35
+ const ms = designTokens.DEFAULT_MOTION.durations[duration];
36
+ if (ms === void 0) throw new Error(`Unknown motion duration token: ${String(duration)}`);
37
+ return ms;
38
+ }
39
+ function resolveEasing(easing) {
40
+ const name = easing ?? DEFAULT_LOGO_EASING;
41
+ const token = designTokens.DEFAULT_MOTION.easings[name];
42
+ if (token === void 0) throw new Error(`Unknown motion easing token: ${String(name)}`);
43
+ return token.css;
44
+ }
45
+
46
+ // src/logo/utils/playLogo.ts
47
+ var ignoreCancel = () => void 0;
48
+ function playLogo(svg, timeline, options = {}) {
49
+ const still = options.reducedMotion ?? prefersReducedMotion();
50
+ const animations = [];
51
+ timeline.forEach((beat) => {
52
+ findLayers(svg, beat.layer).forEach((element) => {
53
+ if (still || !supportsWebAnimations(element)) {
54
+ applyFinalFrame(element, beat.keyframes);
55
+ return;
56
+ }
57
+ animations.push(
58
+ element.animate(beat.keyframes, {
59
+ duration: resolveDuration(beat.duration),
60
+ easing: resolveEasing(beat.easing),
61
+ delay: beat.delay ?? 0,
62
+ fill: "both",
63
+ iterations: options.iterations ?? 1
64
+ })
65
+ );
66
+ });
67
+ });
68
+ const finished = Promise.all(animations.map((animation) => animation.finished.catch(ignoreCancel))).then(ignoreCancel);
69
+ return { finished, cancel: () => animations.forEach((animation) => animation.cancel()) };
70
+ }
71
+
72
+ // src/logo/MicroTrigger.ts
73
+ var MicroTrigger = /* @__PURE__ */ ((MicroTrigger2) => {
74
+ MicroTrigger2["Hover"] = "hover";
75
+ MicroTrigger2["Focus"] = "focus";
76
+ MicroTrigger2["Loading"] = "loading";
77
+ return MicroTrigger2;
78
+ })(MicroTrigger || {});
79
+
80
+ // src/logo/utils/bindMicro.ts
81
+ var START_EVENT = {
82
+ ["hover" /* Hover */]: "pointerenter",
83
+ ["focus" /* Focus */]: "focusin"
84
+ };
85
+ var STOP_EVENT = {
86
+ ["hover" /* Hover */]: "pointerleave",
87
+ ["focus" /* Focus */]: "focusout"
88
+ };
89
+ var noop = () => void 0;
90
+ function bindMicro(svg, timeline, trigger, options = {}) {
91
+ if (options.reducedMotion ?? prefersReducedMotion()) return noop;
92
+ let playback;
93
+ const stop = () => {
94
+ playback?.cancel();
95
+ playback = void 0;
96
+ };
97
+ if (trigger === "loading" /* Loading */) {
98
+ playback = playLogo(svg, timeline, { reducedMotion: false, iterations: Infinity });
99
+ return stop;
100
+ }
101
+ const start = () => {
102
+ stop();
103
+ playback = playLogo(svg, timeline, { reducedMotion: false });
104
+ };
105
+ const startEvent = START_EVENT[trigger] ?? "";
106
+ const stopEvent = STOP_EVENT[trigger] ?? "";
107
+ svg.addEventListener(startEvent, start);
108
+ svg.addEventListener(stopEvent, stop);
109
+ return () => {
110
+ svg.removeEventListener(startEvent, start);
111
+ svg.removeEventListener(stopEvent, stop);
112
+ stop();
113
+ };
114
+ }
115
+
116
+ exports.MOTION_LAYER_ATTRIBUTE = MOTION_LAYER_ATTRIBUTE;
117
+ exports.MicroTrigger = MicroTrigger;
118
+ exports.bindMicro = bindMicro;
119
+ exports.playLogo = playLogo;
120
+ exports.resolveDuration = resolveDuration;
121
+ exports.resolveEasing = resolveEasing;
122
+ //# sourceMappingURL=index.js.map
123
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logo/constants.ts","../../src/logo/utils/layers.ts","../../src/logo/utils/resolveTiming.ts","../../src/logo/utils/playLogo.ts","../../src/logo/MicroTrigger.ts","../../src/logo/utils/bindMicro.ts"],"names":["DEFAULT_MOTION","MicroTrigger"],"mappings":"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","file":"index.js","sourcesContent":["export const MOTION_LAYER_ATTRIBUTE = 'data-motion-layer';\n\nexport const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\nexport const DEFAULT_LOGO_EASING = 'standard';\n","import { MOTION_LAYER_ATTRIBUTE, REDUCED_MOTION_QUERY } from '../constants';\n\nconst FRAME_META_KEYS = new Set(['offset', 'easing', 'composite']);\n\ntype StyledElement = Element & ElementCSSInlineStyle;\n\nexport function findLayers(root: Element, layer: string): StyledElement[] {\n const selector = `[${MOTION_LAYER_ATTRIBUTE}=${JSON.stringify(layer)}]`;\n const nodes = Array.from(root.querySelectorAll(selector));\n if (root.matches(selector)) nodes.unshift(root);\n return nodes.filter((node): node is StyledElement => 'style' in node);\n}\n\nexport function applyFinalFrame(element: StyledElement, keyframes: Keyframe[]): void {\n const last = keyframes[keyframes.length - 1];\n if (last === undefined) return;\n const style = element.style as unknown as Record<string, string>;\n Object.entries(last)\n .filter(([key, value]) => !FRAME_META_KEYS.has(key) && value !== null && value !== undefined)\n .forEach(([key, value]) => {\n style[key] = String(value);\n });\n}\n\nexport function supportsWebAnimations(element: Element): boolean {\n return typeof element.animate === 'function';\n}\n\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","import { DEFAULT_MOTION } from '@dloizides/design-tokens';\n\nimport { DEFAULT_LOGO_EASING } from '../constants';\nimport type { LogoDurationToken, LogoEasingToken } from '../types';\n\n/** A duration token (`fast`, `base`, `slow`, `instant`) to ms; a number passes through. */\nexport function resolveDuration(duration: LogoDurationToken | number): number {\n if (typeof duration === 'number') return duration;\n const ms = DEFAULT_MOTION.durations[duration] as number | undefined;\n if (ms === undefined) throw new Error(`Unknown motion duration token: ${String(duration)}`);\n return ms;\n}\n\n/** An easing token to its css timing function; no token means `standard`. */\nexport function resolveEasing(easing: LogoEasingToken | undefined): string {\n const name = easing ?? DEFAULT_LOGO_EASING;\n const token = DEFAULT_MOTION.easings[name] as { css: string } | undefined;\n if (token === undefined) throw new Error(`Unknown motion easing token: ${String(name)}`);\n return token.css;\n}\n","import type { LogoPlayback, LogoTimeline, PlayLogoOptions } from '../types';\nimport { applyFinalFrame, findLayers, prefersReducedMotion, supportsWebAnimations } from './layers';\nimport { resolveDuration, resolveEasing } from './resolveTiming';\n\nconst ignoreCancel = (): undefined => undefined;\n\n/** Plays a logo timeline on the mark's `data-motion-layer` nodes via the Web Animations API. */\nexport function playLogo(svg: Element, timeline: LogoTimeline, options: PlayLogoOptions = {}): LogoPlayback {\n const still = options.reducedMotion ?? prefersReducedMotion();\n const animations: Animation[] = [];\n timeline.forEach((beat) => {\n findLayers(svg, beat.layer).forEach((element) => {\n if (still || !supportsWebAnimations(element)) {\n applyFinalFrame(element, beat.keyframes);\n return;\n }\n animations.push(\n element.animate(beat.keyframes, {\n duration: resolveDuration(beat.duration),\n easing: resolveEasing(beat.easing),\n delay: beat.delay ?? 0,\n fill: 'both',\n iterations: options.iterations ?? 1,\n }),\n );\n });\n });\n const finished = Promise.all(animations.map((animation) => animation.finished.catch(ignoreCancel))).then(ignoreCancel);\n return { finished, cancel: () => animations.forEach((animation) => animation.cancel()) };\n}\n","/** What starts a logo micro-animation bound with `bindMicro`. */\nexport const enum MicroTrigger {\n Hover = 'hover',\n Focus = 'focus',\n Loading = 'loading',\n}\n","import { MicroTrigger } from '../MicroTrigger';\nimport type { BindMicroOptions, LogoPlayback, LogoTimeline } from '../types';\nimport { prefersReducedMotion } from './layers';\nimport { playLogo } from './playLogo';\n\nconst START_EVENT: Record<string, string | undefined> = {\n [MicroTrigger.Hover]: 'pointerenter',\n [MicroTrigger.Focus]: 'focusin',\n};\n\nconst STOP_EVENT: Record<string, string | undefined> = {\n [MicroTrigger.Hover]: 'pointerleave',\n [MicroTrigger.Focus]: 'focusout',\n};\n\nconst noop = (): void => undefined;\n\n/** Binds a micro-animation to hover, focus or loading; returns the unbind function. */\nexport function bindMicro(\n svg: Element,\n timeline: LogoTimeline,\n trigger: MicroTrigger | `${MicroTrigger}`,\n options: BindMicroOptions = {},\n): () => void {\n if (options.reducedMotion ?? prefersReducedMotion()) return noop;\n let playback: LogoPlayback | undefined;\n const stop = (): void => {\n playback?.cancel();\n playback = undefined;\n };\n if (trigger === MicroTrigger.Loading) {\n playback = playLogo(svg, timeline, { reducedMotion: false, iterations: Infinity });\n return stop;\n }\n const start = (): void => {\n stop();\n playback = playLogo(svg, timeline, { reducedMotion: false });\n };\n const startEvent = START_EVENT[trigger] ?? '';\n const stopEvent = STOP_EVENT[trigger] ?? '';\n svg.addEventListener(startEvent, start);\n svg.addEventListener(stopEvent, stop);\n return () => {\n svg.removeEventListener(startEvent, start);\n svg.removeEventListener(stopEvent, stop);\n stop();\n };\n}\n"]}
@@ -0,0 +1,116 @@
1
+ import { DEFAULT_MOTION } from '@dloizides/design-tokens';
2
+
3
+ // src/logo/constants.ts
4
+ var MOTION_LAYER_ATTRIBUTE = "data-motion-layer";
5
+ var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
6
+ var DEFAULT_LOGO_EASING = "standard";
7
+
8
+ // src/logo/utils/layers.ts
9
+ var FRAME_META_KEYS = /* @__PURE__ */ new Set(["offset", "easing", "composite"]);
10
+ function findLayers(root, layer) {
11
+ const selector = `[${MOTION_LAYER_ATTRIBUTE}=${JSON.stringify(layer)}]`;
12
+ const nodes = Array.from(root.querySelectorAll(selector));
13
+ if (root.matches(selector)) nodes.unshift(root);
14
+ return nodes.filter((node) => "style" in node);
15
+ }
16
+ function applyFinalFrame(element, keyframes) {
17
+ const last = keyframes[keyframes.length - 1];
18
+ if (last === void 0) return;
19
+ const style = element.style;
20
+ Object.entries(last).filter(([key, value]) => !FRAME_META_KEYS.has(key) && value !== null && value !== void 0).forEach(([key, value]) => {
21
+ style[key] = String(value);
22
+ });
23
+ }
24
+ function supportsWebAnimations(element) {
25
+ return typeof element.animate === "function";
26
+ }
27
+ function prefersReducedMotion() {
28
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
29
+ return window.matchMedia(REDUCED_MOTION_QUERY).matches;
30
+ }
31
+ function resolveDuration(duration) {
32
+ if (typeof duration === "number") return duration;
33
+ const ms = DEFAULT_MOTION.durations[duration];
34
+ if (ms === void 0) throw new Error(`Unknown motion duration token: ${String(duration)}`);
35
+ return ms;
36
+ }
37
+ function resolveEasing(easing) {
38
+ const name = easing ?? DEFAULT_LOGO_EASING;
39
+ const token = DEFAULT_MOTION.easings[name];
40
+ if (token === void 0) throw new Error(`Unknown motion easing token: ${String(name)}`);
41
+ return token.css;
42
+ }
43
+
44
+ // src/logo/utils/playLogo.ts
45
+ var ignoreCancel = () => void 0;
46
+ function playLogo(svg, timeline, options = {}) {
47
+ const still = options.reducedMotion ?? prefersReducedMotion();
48
+ const animations = [];
49
+ timeline.forEach((beat) => {
50
+ findLayers(svg, beat.layer).forEach((element) => {
51
+ if (still || !supportsWebAnimations(element)) {
52
+ applyFinalFrame(element, beat.keyframes);
53
+ return;
54
+ }
55
+ animations.push(
56
+ element.animate(beat.keyframes, {
57
+ duration: resolveDuration(beat.duration),
58
+ easing: resolveEasing(beat.easing),
59
+ delay: beat.delay ?? 0,
60
+ fill: "both",
61
+ iterations: options.iterations ?? 1
62
+ })
63
+ );
64
+ });
65
+ });
66
+ const finished = Promise.all(animations.map((animation) => animation.finished.catch(ignoreCancel))).then(ignoreCancel);
67
+ return { finished, cancel: () => animations.forEach((animation) => animation.cancel()) };
68
+ }
69
+
70
+ // src/logo/MicroTrigger.ts
71
+ var MicroTrigger = /* @__PURE__ */ ((MicroTrigger2) => {
72
+ MicroTrigger2["Hover"] = "hover";
73
+ MicroTrigger2["Focus"] = "focus";
74
+ MicroTrigger2["Loading"] = "loading";
75
+ return MicroTrigger2;
76
+ })(MicroTrigger || {});
77
+
78
+ // src/logo/utils/bindMicro.ts
79
+ var START_EVENT = {
80
+ ["hover" /* Hover */]: "pointerenter",
81
+ ["focus" /* Focus */]: "focusin"
82
+ };
83
+ var STOP_EVENT = {
84
+ ["hover" /* Hover */]: "pointerleave",
85
+ ["focus" /* Focus */]: "focusout"
86
+ };
87
+ var noop = () => void 0;
88
+ function bindMicro(svg, timeline, trigger, options = {}) {
89
+ if (options.reducedMotion ?? prefersReducedMotion()) return noop;
90
+ let playback;
91
+ const stop = () => {
92
+ playback?.cancel();
93
+ playback = void 0;
94
+ };
95
+ if (trigger === "loading" /* Loading */) {
96
+ playback = playLogo(svg, timeline, { reducedMotion: false, iterations: Infinity });
97
+ return stop;
98
+ }
99
+ const start = () => {
100
+ stop();
101
+ playback = playLogo(svg, timeline, { reducedMotion: false });
102
+ };
103
+ const startEvent = START_EVENT[trigger] ?? "";
104
+ const stopEvent = STOP_EVENT[trigger] ?? "";
105
+ svg.addEventListener(startEvent, start);
106
+ svg.addEventListener(stopEvent, stop);
107
+ return () => {
108
+ svg.removeEventListener(startEvent, start);
109
+ svg.removeEventListener(stopEvent, stop);
110
+ stop();
111
+ };
112
+ }
113
+
114
+ export { MOTION_LAYER_ATTRIBUTE, MicroTrigger, bindMicro, playLogo, resolveDuration, resolveEasing };
115
+ //# sourceMappingURL=index.mjs.map
116
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logo/constants.ts","../../src/logo/utils/layers.ts","../../src/logo/utils/resolveTiming.ts","../../src/logo/utils/playLogo.ts","../../src/logo/MicroTrigger.ts","../../src/logo/utils/bindMicro.ts"],"names":["MicroTrigger"],"mappings":";;;AAAO,IAAM,sBAAA,GAAyB;AAE/B,IAAM,oBAAA,GAAuB,kCAAA;AAE7B,IAAM,mBAAA,GAAsB,UAAA;;;ACFnC,IAAM,kCAAkB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,QAAA,EAAU,WAAW,CAAC,CAAA;AAI1D,SAAS,UAAA,CAAW,MAAe,KAAA,EAAgC;AACxE,EAAA,MAAM,WAAW,CAAA,CAAA,EAAI,sBAAsB,IAAI,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,CAAA,CAAA;AACpE,EAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,QAAQ,CAAC,CAAA;AACxD,EAAA,IAAI,KAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG,KAAA,CAAM,QAAQ,IAAI,CAAA;AAC9C,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,IAAA,KAAgC,WAAW,IAAI,CAAA;AACtE;AAEO,SAAS,eAAA,CAAgB,SAAwB,SAAA,EAA6B;AACnF,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,SAAA,CAAU,MAAA,GAAS,CAAC,CAAA;AAC3C,EAAA,IAAI,SAAS,MAAA,EAAW;AACxB,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA;AACtB,EAAA,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,CAChB,MAAA,CAAO,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM,CAAC,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAA,IAAK,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAS,CAAA,CAC3F,QAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AACzB,IAAA,KAAA,CAAM,GAAG,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAAA,EAC3B,CAAC,CAAA;AACL;AAEO,SAAS,sBAAsB,OAAA,EAA2B;AAC/D,EAAA,OAAO,OAAO,QAAQ,OAAA,KAAY,UAAA;AACpC;AAEO,SAAS,oBAAA,GAAgC;AAC9C,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,MAAA,CAAO,UAAA,KAAe,YAAY,OAAO,KAAA;AACrF,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,oBAAoB,CAAA,CAAE,OAAA;AACjD;ACzBO,SAAS,gBAAgB,QAAA,EAA8C;AAC5E,EAAA,IAAI,OAAO,QAAA,KAAa,QAAA,EAAU,OAAO,QAAA;AACzC,EAAA,MAAM,EAAA,GAAK,cAAA,CAAe,SAAA,CAAU,QAAQ,CAAA;AAC5C,EAAA,IAAI,EAAA,KAAO,QAAW,MAAM,IAAI,MAAM,CAAA,+BAAA,EAAkC,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAE,CAAA;AAC1F,EAAA,OAAO,EAAA;AACT;AAGO,SAAS,cAAc,MAAA,EAA6C;AACzE,EAAA,MAAM,OAAO,MAAA,IAAU,mBAAA;AACvB,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,CAAQ,IAAI,CAAA;AACzC,EAAA,IAAI,KAAA,KAAU,QAAW,MAAM,IAAI,MAAM,CAAA,6BAAA,EAAgC,MAAA,CAAO,IAAI,CAAC,CAAA,CAAE,CAAA;AACvF,EAAA,OAAO,KAAA,CAAM,GAAA;AACf;;;ACfA,IAAM,eAAe,MAAiB,MAAA;AAG/B,SAAS,QAAA,CAAS,GAAA,EAAc,QAAA,EAAwB,OAAA,GAA2B,EAAC,EAAiB;AAC1G,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,aAAA,IAAiB,oBAAA,EAAqB;AAC5D,EAAA,MAAM,aAA0B,EAAC;AACjC,EAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,IAAA,KAAS;AACzB,IAAA,UAAA,CAAW,KAAK,IAAA,CAAK,KAAK,CAAA,CAAE,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC/C,MAAA,IAAI,KAAA,IAAS,CAAC,qBAAA,CAAsB,OAAO,CAAA,EAAG;AAC5C,QAAA,eAAA,CAAgB,OAAA,EAAS,KAAK,SAAS,CAAA;AACvC,QAAA;AAAA,MACF;AACA,MAAA,UAAA,CAAW,IAAA;AAAA,QACT,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,SAAA,EAAW;AAAA,UAC9B,QAAA,EAAU,eAAA,CAAgB,IAAA,CAAK,QAAQ,CAAA;AAAA,UACvC,MAAA,EAAQ,aAAA,CAAc,IAAA,CAAK,MAAM,CAAA;AAAA,UACjC,KAAA,EAAO,KAAK,KAAA,IAAS,CAAA;AAAA,UACrB,IAAA,EAAM,MAAA;AAAA,UACN,UAAA,EAAY,QAAQ,UAAA,IAAc;AAAA,SACnC;AAAA,OACH;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,UAAA,CAAW,IAAI,CAAC,SAAA,KAAc,SAAA,CAAU,QAAA,CAAS,MAAM,YAAY,CAAC,CAAC,CAAA,CAAE,KAAK,YAAY,CAAA;AACrH,EAAA,OAAO,EAAE,QAAA,EAAU,MAAA,EAAQ,MAAM,UAAA,CAAW,OAAA,CAAQ,CAAC,SAAA,KAAc,SAAA,CAAU,MAAA,EAAQ,CAAA,EAAE;AACzF;;;AC5BO,IAAW,YAAA,qBAAAA,aAAAA,KAAX;AACL,EAAAA,cAAA,OAAA,CAAA,GAAQ,OAAA;AACR,EAAAA,cAAA,OAAA,CAAA,GAAQ,OAAA;AACR,EAAAA,cAAA,SAAA,CAAA,GAAU,SAAA;AAHM,EAAA,OAAAA,aAAAA;AAAA,CAAA,EAAA,YAAA,IAAA,EAAA;;;ACIlB,IAAM,WAAA,GAAkD;AAAA,EACtD,uBAAsB,cAAA;AAAA,EACtB,uBAAsB;AACxB,CAAA;AAEA,IAAM,UAAA,GAAiD;AAAA,EACrD,uBAAsB,cAAA;AAAA,EACtB,uBAAsB;AACxB,CAAA;AAEA,IAAM,OAAO,MAAY,MAAA;AAGlB,SAAS,UACd,GAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,GAA4B,EAAC,EACjB;AACZ,EAAA,IAAI,OAAA,CAAQ,aAAA,IAAiB,oBAAA,EAAqB,EAAG,OAAO,IAAA;AAC5D,EAAA,IAAI,QAAA;AACJ,EAAA,MAAM,OAAO,MAAY;AACvB,IAAA,QAAA,EAAU,MAAA,EAAO;AACjB,IAAA,QAAA,GAAW,MAAA;AAAA,EACb,CAAA;AACA,EAAA,IAAI,OAAA,KAAA,SAAA,gBAAkC;AACpC,IAAA,QAAA,GAAW,QAAA,CAAS,KAAK,QAAA,EAAU,EAAE,eAAe,KAAA,EAAO,UAAA,EAAY,UAAU,CAAA;AACjF,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAQ,MAAY;AACxB,IAAA,IAAA,EAAK;AACL,IAAA,QAAA,GAAW,SAAS,GAAA,EAAK,QAAA,EAAU,EAAE,aAAA,EAAe,OAAO,CAAA;AAAA,EAC7D,CAAA;AACA,EAAA,MAAM,UAAA,GAAa,WAAA,CAAY,OAAO,CAAA,IAAK,EAAA;AAC3C,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,OAAO,CAAA,IAAK,EAAA;AACzC,EAAA,GAAA,CAAI,gBAAA,CAAiB,YAAY,KAAK,CAAA;AACtC,EAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,IAAI,CAAA;AACpC,EAAA,OAAO,MAAM;AACX,IAAA,GAAA,CAAI,mBAAA,CAAoB,YAAY,KAAK,CAAA;AACzC,IAAA,GAAA,CAAI,mBAAA,CAAoB,WAAW,IAAI,CAAA;AACvC,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AACF","file":"index.mjs","sourcesContent":["export const MOTION_LAYER_ATTRIBUTE = 'data-motion-layer';\n\nexport const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\nexport const DEFAULT_LOGO_EASING = 'standard';\n","import { MOTION_LAYER_ATTRIBUTE, REDUCED_MOTION_QUERY } from '../constants';\n\nconst FRAME_META_KEYS = new Set(['offset', 'easing', 'composite']);\n\ntype StyledElement = Element & ElementCSSInlineStyle;\n\nexport function findLayers(root: Element, layer: string): StyledElement[] {\n const selector = `[${MOTION_LAYER_ATTRIBUTE}=${JSON.stringify(layer)}]`;\n const nodes = Array.from(root.querySelectorAll(selector));\n if (root.matches(selector)) nodes.unshift(root);\n return nodes.filter((node): node is StyledElement => 'style' in node);\n}\n\nexport function applyFinalFrame(element: StyledElement, keyframes: Keyframe[]): void {\n const last = keyframes[keyframes.length - 1];\n if (last === undefined) return;\n const style = element.style as unknown as Record<string, string>;\n Object.entries(last)\n .filter(([key, value]) => !FRAME_META_KEYS.has(key) && value !== null && value !== undefined)\n .forEach(([key, value]) => {\n style[key] = String(value);\n });\n}\n\nexport function supportsWebAnimations(element: Element): boolean {\n return typeof element.animate === 'function';\n}\n\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","import { DEFAULT_MOTION } from '@dloizides/design-tokens';\n\nimport { DEFAULT_LOGO_EASING } from '../constants';\nimport type { LogoDurationToken, LogoEasingToken } from '../types';\n\n/** A duration token (`fast`, `base`, `slow`, `instant`) to ms; a number passes through. */\nexport function resolveDuration(duration: LogoDurationToken | number): number {\n if (typeof duration === 'number') return duration;\n const ms = DEFAULT_MOTION.durations[duration] as number | undefined;\n if (ms === undefined) throw new Error(`Unknown motion duration token: ${String(duration)}`);\n return ms;\n}\n\n/** An easing token to its css timing function; no token means `standard`. */\nexport function resolveEasing(easing: LogoEasingToken | undefined): string {\n const name = easing ?? DEFAULT_LOGO_EASING;\n const token = DEFAULT_MOTION.easings[name] as { css: string } | undefined;\n if (token === undefined) throw new Error(`Unknown motion easing token: ${String(name)}`);\n return token.css;\n}\n","import type { LogoPlayback, LogoTimeline, PlayLogoOptions } from '../types';\nimport { applyFinalFrame, findLayers, prefersReducedMotion, supportsWebAnimations } from './layers';\nimport { resolveDuration, resolveEasing } from './resolveTiming';\n\nconst ignoreCancel = (): undefined => undefined;\n\n/** Plays a logo timeline on the mark's `data-motion-layer` nodes via the Web Animations API. */\nexport function playLogo(svg: Element, timeline: LogoTimeline, options: PlayLogoOptions = {}): LogoPlayback {\n const still = options.reducedMotion ?? prefersReducedMotion();\n const animations: Animation[] = [];\n timeline.forEach((beat) => {\n findLayers(svg, beat.layer).forEach((element) => {\n if (still || !supportsWebAnimations(element)) {\n applyFinalFrame(element, beat.keyframes);\n return;\n }\n animations.push(\n element.animate(beat.keyframes, {\n duration: resolveDuration(beat.duration),\n easing: resolveEasing(beat.easing),\n delay: beat.delay ?? 0,\n fill: 'both',\n iterations: options.iterations ?? 1,\n }),\n );\n });\n });\n const finished = Promise.all(animations.map((animation) => animation.finished.catch(ignoreCancel))).then(ignoreCancel);\n return { finished, cancel: () => animations.forEach((animation) => animation.cancel()) };\n}\n","/** What starts a logo micro-animation bound with `bindMicro`. */\nexport const enum MicroTrigger {\n Hover = 'hover',\n Focus = 'focus',\n Loading = 'loading',\n}\n","import { MicroTrigger } from '../MicroTrigger';\nimport type { BindMicroOptions, LogoPlayback, LogoTimeline } from '../types';\nimport { prefersReducedMotion } from './layers';\nimport { playLogo } from './playLogo';\n\nconst START_EVENT: Record<string, string | undefined> = {\n [MicroTrigger.Hover]: 'pointerenter',\n [MicroTrigger.Focus]: 'focusin',\n};\n\nconst STOP_EVENT: Record<string, string | undefined> = {\n [MicroTrigger.Hover]: 'pointerleave',\n [MicroTrigger.Focus]: 'focusout',\n};\n\nconst noop = (): void => undefined;\n\n/** Binds a micro-animation to hover, focus or loading; returns the unbind function. */\nexport function bindMicro(\n svg: Element,\n timeline: LogoTimeline,\n trigger: MicroTrigger | `${MicroTrigger}`,\n options: BindMicroOptions = {},\n): () => void {\n if (options.reducedMotion ?? prefersReducedMotion()) return noop;\n let playback: LogoPlayback | undefined;\n const stop = (): void => {\n playback?.cancel();\n playback = undefined;\n };\n if (trigger === MicroTrigger.Loading) {\n playback = playLogo(svg, timeline, { reducedMotion: false, iterations: Infinity });\n return stop;\n }\n const start = (): void => {\n stop();\n playback = playLogo(svg, timeline, { reducedMotion: false });\n };\n const startEvent = START_EVENT[trigger] ?? '';\n const stopEvent = STOP_EVENT[trigger] ?? '';\n svg.addEventListener(startEvent, start);\n svg.addEventListener(stopEvent, stop);\n return () => {\n svg.removeEventListener(startEvent, start);\n svg.removeEventListener(stopEvent, stop);\n stop();\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dloizides/ui-motion",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Themable, brand-agnostic React Native (RN-web) motion primitives — useEnterExit, FadeIn, Collapse, PressableScale, Skeleton — built on RN Animated, driven by @dloizides/design-tokens motion tokens, and gated on @dloizides/rn-web-hooks useReducedMotion (every animation collapses to instant under reduced-motion). Part of the dloizides.com shared UI kit.",
5
5
  "keywords": [
6
6
  "react",
@@ -70,6 +70,18 @@
70
70
  "types": "./dist/hairline/web.d.ts",
71
71
  "default": "./dist/hairline/web.js"
72
72
  }
73
+ },
74
+ "./logo": {
75
+ "types": "./dist/logo/index.d.ts",
76
+ "import": {
77
+ "types": "./dist/logo/index.d.mts",
78
+ "default": "./dist/logo/index.mjs"
79
+ },
80
+ "require": {
81
+ "types": "./dist/logo/index.d.ts",
82
+ "default": "./dist/logo/index.js"
83
+ },
84
+ "default": "./dist/logo/index.js"
73
85
  }
74
86
  },
75
87
  "files": [
@@ -94,7 +106,7 @@
94
106
  "security:audit": "npm audit --audit-level=high",
95
107
  "deps:outdated": "npm outdated || exit 0",
96
108
  "deps:unused": "npx depcheck --ignores \"@types/jest,@types/node,@types/react,@types/react-dom,rimraf,react-native,react-native-webview\"",
97
- "deps:licenses": "npx license-checker --onlyAllow \"MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;0BSD;Unlicense;CC0-1.0\"",
109
+ "deps:licenses": "npx license-checker --production --onlyAllow \"MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;0BSD;Unlicense;CC0-1.0;CC-BY-3.0;CC-BY-4.0;Python-2.0;BlueOak-1.0.0\" && npx license-checker --development --onlyAllow \"MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;0BSD;Unlicense;CC0-1.0;CC-BY-3.0;CC-BY-4.0;Python-2.0;BlueOak-1.0.0;LGPL-3.0;LGPL-3.0-only;LGPL-3.0-or-later\"",
98
110
  "deps:health": "npm run deps:outdated && npm run deps:unused",
99
111
  "prepublishOnly": "npm run clean && npm run build && npm run test",
100
112
  "version": "npm run build",
@@ -137,6 +149,12 @@
137
149
  "typescript": "^5.4.0"
138
150
  },
139
151
  "peerDependenciesMeta": {
152
+ "react": {
153
+ "optional": true
154
+ },
155
+ "react-native": {
156
+ "optional": true
157
+ },
140
158
  "react-native-webview": {
141
159
  "optional": true
142
160
  }