@inc2734/unitone-css 1.4.1 → 1.4.2

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.
Files changed (34) hide show
  1. package/dist/app.css +1 -1
  2. package/dist/app.js +1 -1
  3. package/dist/behaviors/dividers.js +1 -1
  4. package/dist/behaviors/index.js +1 -1
  5. package/dist/behaviors/stairs.js +1 -1
  6. package/dist/layout-primitives/cluster/react.js +1 -1
  7. package/dist/layout-primitives/index.js +1 -1
  8. package/dist/layout-primitives/marquee/behavior.js +1 -1
  9. package/dist/layout-primitives/marquee/react.js +1 -1
  10. package/dist/layout-primitives/responsive-grid/react.js +1 -1
  11. package/dist/layout-primitives/stack/react.js +1 -1
  12. package/dist/layout-primitives/switcher/react.js +1 -1
  13. package/dist/layout-primitives/vertical-writing/behavior.js +1 -1
  14. package/dist/layout-primitives/vertical-writing/react.js +1 -1
  15. package/dist/layout-primitives/with-sidebar/react.js +1 -1
  16. package/dist/library.js +1 -1
  17. package/package.json +1 -1
  18. package/src/behaviors/dividers.js +3 -1
  19. package/src/behaviors/stairs.js +3 -1
  20. package/src/layout-behavior-state.js +41 -0
  21. package/src/layout-primitives/cluster/index.jsx +25 -16
  22. package/src/layout-primitives/marquee/_index.scss +15 -7
  23. package/src/layout-primitives/marquee/behavior.js +1 -1
  24. package/src/layout-primitives/marquee/index.jsx +69 -7
  25. package/src/layout-primitives/marquee/layout.js +163 -0
  26. package/src/layout-primitives/responsive-grid/index.jsx +29 -17
  27. package/src/layout-primitives/stack/index.jsx +25 -16
  28. package/src/layout-primitives/switcher/index.jsx +26 -17
  29. package/src/layout-primitives/vertical-writing/behavior.js +3 -1
  30. package/src/layout-primitives/vertical-writing/index.jsx +11 -11
  31. package/src/layout-primitives/with-sidebar/index.jsx +27 -18
  32. package/src/library.js +162 -298
  33. package/src/register-layout-initializer.js +34 -24
  34. package/src/use-layout-behaviors.js +60 -0
@@ -22,32 +22,29 @@ const getRegistry = () => {
22
22
  return globalThis[INITIALIZER_REGISTRY_KEY];
23
23
  };
24
24
 
25
- const initializeInitializer = (initializer, root) => {
26
- if (!root?.isConnected || !initializer.enabled() || root.nodeType !== Node.ELEMENT_NODE) {
27
- return;
28
- }
29
-
30
- const targets = new Set();
31
-
32
- if (root.matches?.(initializer.selector)) {
33
- targets.add(root);
34
- }
35
-
36
- root.querySelectorAll?.(initializer.selector).forEach((target) => {
37
- targets.add(target);
38
- });
39
-
40
- targets.forEach((target) => {
25
+ const initializeTarget = (initializer, target) => {
26
+ if (!target?.isConnected || target.nodeType !== Node.ELEMENT_NODE) return;
27
+ if (!initializer.enabled() || !target.matches?.(initializer.selector)) {
41
28
  if (initializer.initialized.has(target)) {
42
- return;
29
+ initializer.cleanups.get(target)?.();
30
+ initializer.cleanups.delete(target);
31
+ initializer.initialized.delete(target);
32
+ initializer.reset?.(target);
43
33
  }
34
+ return;
35
+ }
36
+ if (initializer.initialized.has(target)) return;
37
+ const cleanup = initializer.initialize(target);
38
+ initializer.initialized.add(target);
39
+ if (typeof cleanup === 'function') initializer.cleanups.set(target, cleanup);
40
+ };
44
41
 
45
- const cleanup = initializer.initialize(target);
46
- initializer.initialized.add(target);
47
- if ('function' === typeof cleanup) {
48
- initializer.cleanups.set(target, cleanup);
49
- }
50
- });
42
+ const initializeInitializer = (initializer, root) => {
43
+ if (!root?.isConnected || root.nodeType !== Node.ELEMENT_NODE) return;
44
+ initializeTarget(initializer, root);
45
+ root
46
+ .querySelectorAll?.(initializer.selector)
47
+ .forEach((target) => initializeTarget(initializer, target));
51
48
  };
52
49
 
53
50
  const initializeNode = (root) => {
@@ -106,6 +103,10 @@ const observeDocument = () => {
106
103
 
107
104
  registry.observer = new MutationObserver((entries) => {
108
105
  entries.forEach((entry) => {
106
+ if (entry.type === 'attributes') {
107
+ registry.initializers.forEach((initializer) => initializeTarget(initializer, entry.target));
108
+ return;
109
+ }
109
110
  entry.removedNodes.forEach(disposeNode);
110
111
  entry.addedNodes.forEach((addedNode) => {
111
112
  if (addedNode?.isConnected && addedNode.nodeType === Node.ELEMENT_NODE) {
@@ -126,12 +127,20 @@ const observeDocument = () => {
126
127
  });
127
128
 
128
129
  registry.observer.observe(document.body, {
130
+ attributes: true,
131
+ attributeFilter: ['data-unitone-layout', 'data-unitone-react-layout'],
129
132
  childList: true,
130
133
  subtree: true,
131
134
  });
132
135
  };
133
136
 
134
- export const registerLayoutInitializer = ({ key, selector, initialize, enabled = () => true }) => {
137
+ export const registerLayoutInitializer = ({
138
+ key,
139
+ selector,
140
+ initialize,
141
+ reset,
142
+ enabled = () => true,
143
+ }) => {
135
144
  const registry = getRegistry();
136
145
  if (!registry || registry.initializers.has(key)) {
137
146
  return;
@@ -140,6 +149,7 @@ export const registerLayoutInitializer = ({ key, selector, initialize, enabled =
140
149
  const initializer = {
141
150
  selector,
142
151
  initialize,
152
+ reset,
143
153
  enabled,
144
154
  initialized: new WeakSet(),
145
155
  cleanups: new WeakMap(),
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useImperativeHandle, useLayoutEffect, useRef } from 'react';
4
+ import { dividersResizeObserver, stairsResizeObserver, verticalsResizeObserver } from './library';
5
+ import { layoutRefreshEvent, resetLayoutBehavior } from './layout-behavior-state';
6
+
7
+ const useBrowserLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
8
+ const observers = {
9
+ divider: dividersResizeObserver,
10
+ stairs: stairsResizeObserver,
11
+ vertical: verticalsResizeObserver,
12
+ };
13
+
14
+ /** React owns observer lifetimes; calculations and resize handling remain shared with HTML. */
15
+ export const useLayoutBehaviors = (enabled, forwardedRef) => {
16
+ const targetRef = useRef(null);
17
+ const lifetimeRef = useRef(null);
18
+ useImperativeHandle(forwardedRef, () => targetRef.current);
19
+
20
+ const dispose = () => {
21
+ const lifetime = lifetimeRef.current;
22
+ if (!lifetime) return;
23
+ lifetime.target.removeEventListener(layoutRefreshEvent, lifetime.refresh);
24
+ lifetime.controllers.forEach((controller, name) => {
25
+ controller.dispose();
26
+ resetLayoutBehavior(lifetime.target, name);
27
+ });
28
+ lifetimeRef.current = null;
29
+ };
30
+
31
+ useBrowserLayoutEffect(() => dispose, []);
32
+ useBrowserLayoutEffect(() => {
33
+ const target = targetRef.current;
34
+ if (lifetimeRef.current?.target !== target) dispose();
35
+ if (!target) return;
36
+ if (!lifetimeRef.current) {
37
+ const controllers = new Map();
38
+ const refresh = () => controllers.forEach((controller) => controller.refresh());
39
+ lifetimeRef.current = { target, controllers, refresh };
40
+ target.addEventListener(layoutRefreshEvent, refresh);
41
+ }
42
+ const { controllers } = lifetimeRef.current;
43
+ for (const [name, observe] of Object.entries(observers)) {
44
+ if (!enabled[name]) {
45
+ if (controllers.has(name)) {
46
+ controllers.get(name).dispose();
47
+ controllers.delete(name);
48
+ resetLayoutBehavior(target, name);
49
+ }
50
+ } else if (!controllers.has(name)) {
51
+ const stop = observe(target, { reactOwned: true });
52
+ controllers.set(name, { dispose: stop, refresh: stop.refresh });
53
+ } else {
54
+ controllers.get(name).refresh();
55
+ }
56
+ }
57
+ });
58
+
59
+ return targetRef;
60
+ };