@vitus-labs/elements 1.4.3-alpha.3 → 1.4.3-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { Provider } from "@vitus-labs/unistyle";
2
2
  import { BreakpointKeys, HTMLTags, HTMLTextTags, config, render } from "@vitus-labs/core";
3
3
  import * as react from "react";
4
- import { ComponentType, FC, ForwardRefExoticComponent, ForwardedRef, PropsWithoutRef, ReactNode, Ref, RefAttributes } from "react";
5
- import * as react_jsx_runtime0 from "react/jsx-runtime";
4
+ import { ComponentType, FC, ForwardRefExoticComponent, ForwardedRef, PropsWithoutRef, ReactNode, RefAttributes } from "react";
6
5
 
7
6
  //#region src/types.d.ts
8
7
  type ExtractNullableKeys<T> = { [P in keyof T as T[P] extends null | undefined ? never : P]: T[P] };
@@ -10,7 +9,6 @@ type Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
10
9
  type SpreadTwo<L, R> = Id<Pick<L, Exclude<keyof L, keyof R>> & R>;
11
10
  type Spread<A extends readonly [...any]> = A extends [infer L, ...infer R] ? SpreadTwo<L, Spread<R>> : unknown;
12
11
  type MergeTypes<A extends readonly [...any]> = ExtractNullableKeys<Spread<A>>;
13
- type SimpleHoc<P extends Record<string, unknown> = {}> = (WrappedComponent: ComponentType<P>) => ComponentType<P>;
14
12
  type InnerRef = ForwardedRef<any>;
15
13
  type CssCallback = (css: typeof config.css) => ReturnType<typeof css>;
16
14
  type Css = CssCallback | ReturnType<typeof config.css> | string;
@@ -109,6 +107,14 @@ type Props = Partial<{
109
107
  * (have the same width or height)
110
108
  */
111
109
  equalCols: ResponsiveBoolType;
110
+ /**
111
+ * When true, measures the `beforeContent` and `afterContent` slot wrappers
112
+ * after render and sets both to the larger dimension so they match.
113
+ * Uses width for inline direction and height for rows direction.
114
+ * Useful for centering the main content when before/after slots have
115
+ * different intrinsic sizes.
116
+ */
117
+ equalBeforeAfter: boolean;
112
118
  /**
113
119
  * Defines a `gap` spacing between inner wrappers between `beforeContent` and `children`
114
120
  * and `children` and `afterContent`
@@ -290,23 +296,6 @@ type VLElement<P extends Record<string, unknown> = {}> = ForwardRefExoticCompone
290
296
  //#region src/Element/component.d.ts
291
297
  declare const Component: VLElement;
292
298
  //#endregion
293
- //#region src/Element/withEqualSizeBeforeAfter.d.ts
294
- type Props$8 = Props & Partial<{
295
- equalBeforeAfter: boolean;
296
- ref: Ref<HTMLElement>;
297
- }>;
298
- declare const withEqualBeforeAfter: (WrappedComponent: any) => {
299
- ({
300
- equalBeforeAfter,
301
- direction,
302
- afterContent,
303
- beforeContent,
304
- ref,
305
- ...rest
306
- }: Props$8): react_jsx_runtime0.JSX.Element;
307
- displayName: string;
308
- };
309
- //#endregion
310
299
  //#region src/helpers/Iterator/types.d.ts
311
300
  type MaybeNull = undefined | null;
312
301
  type TObj = Record<string, unknown>;
@@ -386,16 +375,6 @@ type ListProps = {
386
375
  type Props$2 = MergeTypes<[Props$1, ListProps]>;
387
376
  declare const Component$1: VLElement<Props$2>;
388
377
  //#endregion
389
- //#region src/List/withActiveState.d.ts
390
- type Key = string | number;
391
- interface Props$7 {
392
- type?: 'single' | 'multi';
393
- activeItemRequired?: boolean;
394
- activeItems?: Key | (string | number)[];
395
- itemProps?: Record<string, unknown> | ((props: Record<string, unknown>) => Record<string, unknown>);
396
- }
397
- declare const component: SimpleHoc<Props$7>;
398
- //#endregion
399
378
  //#region src/Overlay/context.d.ts
400
379
  interface Context {
401
380
  blocked: boolean;
@@ -643,5 +622,5 @@ interface Props$6 {
643
622
  }
644
623
  declare const Component$6: VLComponent<Props$6>;
645
624
  //#endregion
646
- export { type AlignX, type AlignY, type Content, type ContentBoolean, type Direction, Component as Element, type Props as ElementProps, type ElementType, type ExtendCss, type ExtendedProps, type InnerRef, type Props$1 as IteratorProps, Component$1 as List, type Props$2 as ListProps, type ObjectValue, Component$2 as Overlay, type Props$3 as OverlayProps, Component$3 as OverlayProvider, Component$4 as Portal, type Props$4 as PortalProps, type PropsCallback, Provider, type Responsive, type ResponsiveBoolType, Component$5 as Text, type Props$5 as TextProps, type UseOverlayProps, Component$6 as Util, type Props$6 as UtilProps, type VLStatic, useOverlay, component as withActiveState, withEqualBeforeAfter as withEqualSizeBeforeAfter };
625
+ export { type AlignX, type AlignY, type Content, type ContentBoolean, type Direction, Component as Element, type Props as ElementProps, type ElementType, type ExtendCss, type ExtendedProps, type InnerRef, type Props$1 as IteratorProps, Component$1 as List, type Props$2 as ListProps, type ObjectValue, Component$2 as Overlay, type Props$3 as OverlayProps, Component$3 as OverlayProvider, Component$4 as Portal, type Props$4 as PortalProps, type PropsCallback, Provider, type Responsive, type ResponsiveBoolType, Component$5 as Text, type Props$5 as TextProps, type UseOverlayProps, Component$6 as Util, type Props$6 as UtilProps, type VLStatic, useOverlay };
647
626
  //# sourceMappingURL=index2.d.ts.map
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Provider, alignContent, extendCss, makeItResponsive, value } from "@vitus-labs/unistyle";
2
2
  import { config, context, isEmpty, omit, pick, render, throttle } from "@vitus-labs/core";
3
- import { Children, createContext, forwardRef, memo, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { Children, createContext, forwardRef, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { isFragment } from "react-is";
6
6
  import { createPortal } from "react-dom";
@@ -21,7 +21,7 @@ const IS_DEVELOPMENT = process.env.NODE_ENV !== "production";
21
21
  * equalCols flex distribution. The "content" slot gets `flex: 1` to
22
22
  * fill remaining space between before and after.
23
23
  */
24
- const { styled: styled$2, css: css$2, component: component$2 } = config;
24
+ const { styled: styled$2, css: css$2, component: component$1 } = config;
25
25
  const equalColsCSS = `
26
26
  flex: 1;
27
27
  `;
@@ -67,7 +67,7 @@ const styles$2 = ({ css, theme: t, rootSize }) => css`
67
67
 
68
68
  ${t.extraStyles && extendCss(t.extraStyles)};
69
69
  `;
70
- const StyledComponent = styled$2(component$2)`
70
+ const StyledComponent = styled$2(component$1)`
71
71
  ${`box-sizing: border-box;`};
72
72
 
73
73
  display: flex;
@@ -140,7 +140,7 @@ var Content_default = component_default$1;
140
140
  * split flex behavior across two DOM nodes for button/fieldset/legend
141
141
  * elements where a single flex container is insufficient.
142
142
  */
143
- const { styled: styled$1, css: css$1, component: component$1 } = config;
143
+ const { styled: styled$1, css: css$1, component } = config;
144
144
  const childFixCSS = `
145
145
  display: flex;
146
146
  flex: 1;
@@ -178,7 +178,7 @@ const styles$1 = ({ theme: t, css }) => css`
178
178
  ${t.extraStyles && extendCss(t.extraStyles)};
179
179
  `;
180
180
  const platformCSS = `box-sizing: border-box;`;
181
- var styled_default$1 = styled$1(component$1)`
181
+ var styled_default$1 = styled$1(component)`
182
182
  position: relative;
183
183
  ${platformCSS};
184
184
 
@@ -369,11 +369,26 @@ const getShouldBeEmpty = (tag) => {
369
369
  * like void elements (input, img) and inline elements (span, a) by
370
370
  * skipping children or switching sub-tags accordingly.
371
371
  */
372
+ const equalize = (el, direction) => {
373
+ const beforeEl = el.firstElementChild;
374
+ const afterEl = el.lastElementChild;
375
+ if (beforeEl && afterEl && beforeEl !== afterEl) {
376
+ const type = direction === "rows" ? "height" : "width";
377
+ const prop = type === "height" ? "offsetHeight" : "offsetWidth";
378
+ const beforeSize = beforeEl[prop];
379
+ const afterSize = afterEl[prop];
380
+ if (Number.isInteger(beforeSize) && Number.isInteger(afterSize)) {
381
+ const maxSize = `${Math.max(beforeSize, afterSize)}px`;
382
+ beforeEl.style[type] = maxSize;
383
+ afterEl.style[type] = maxSize;
384
+ }
385
+ }
386
+ };
372
387
  const defaultDirection = "inline";
373
388
  const defaultContentDirection = "rows";
374
389
  const defaultAlignX = "left";
375
390
  const defaultAlignY = "center";
376
- const Component$7 = forwardRef(({ innerRef, tag, label, content, children, beforeContent, afterContent, block, equalCols, gap, direction, alignX = defaultAlignX, alignY = defaultAlignY, css, contentCss, beforeContentCss, afterContentCss, contentDirection = defaultContentDirection, contentAlignX = defaultAlignX, contentAlignY = defaultAlignY, beforeContentDirection = defaultDirection, beforeContentAlignX = defaultAlignX, beforeContentAlignY = defaultAlignY, afterContentDirection = defaultDirection, afterContentAlignX = defaultAlignX, afterContentAlignY = defaultAlignY, ...props }, ref) => {
391
+ const Component$7 = forwardRef(({ innerRef, tag, label, content, children, beforeContent, afterContent, equalBeforeAfter, block, equalCols, gap, direction, alignX = defaultAlignX, alignY = defaultAlignY, css, contentCss, beforeContentCss, afterContentCss, contentDirection = defaultContentDirection, contentAlignX = defaultAlignX, contentAlignY = defaultAlignY, beforeContentDirection = defaultDirection, beforeContentAlignX = defaultAlignX, beforeContentAlignY = defaultAlignY, afterContentDirection = defaultDirection, afterContentAlignX = defaultAlignX, afterContentAlignY = defaultAlignY, ...props }, ref) => {
377
392
  const shouldBeEmpty = !!props.dangerouslySetInnerHTML || getShouldBeEmpty(tag);
378
393
  const isSimpleElement = !beforeContent && !afterContent;
379
394
  const CHILDREN = children ?? content ?? label;
@@ -403,8 +418,24 @@ const Component$7 = forwardRef(({ innerRef, tag, label, content, children, befor
403
418
  alignY,
404
419
  direction
405
420
  ]);
421
+ const equalizeRef = useRef(null);
422
+ const externalRef = ref ?? innerRef;
423
+ const mergedRef = useCallback((node) => {
424
+ equalizeRef.current = node;
425
+ if (typeof externalRef === "function") externalRef(node);
426
+ else if (externalRef != null) externalRef.current = node;
427
+ }, [externalRef]);
428
+ useLayoutEffect(() => {
429
+ if (!equalBeforeAfter || !beforeContent || !afterContent) return;
430
+ if (equalizeRef.current) equalize(equalizeRef.current, direction);
431
+ }, [
432
+ equalBeforeAfter,
433
+ beforeContent,
434
+ afterContent,
435
+ direction
436
+ ]);
406
437
  const WRAPPER_PROPS = {
407
- ref: ref ?? innerRef,
438
+ ref: mergedRef,
408
439
  extendCss: css,
409
440
  tag,
410
441
  block,
@@ -465,58 +496,6 @@ Component$7.displayName = name$5;
465
496
  Component$7.pkgName = PKG_NAME;
466
497
  Component$7.VITUS_LABS__COMPONENT = name$5;
467
498
 
468
- //#endregion
469
- //#region src/Element/withEqualSizeBeforeAfter.tsx
470
- /**
471
- * HOC that equalizes the dimensions of beforeContent and afterContent areas.
472
- * After render, it measures both DOM nodes via useLayoutEffect and sets the
473
- * larger dimension on both so they match. Uses width for inline direction
474
- * and height for rows direction. This is useful for centering the main
475
- * content when before/after slots have different intrinsic sizes.
476
- */
477
- const types = {
478
- height: "offsetHeight",
479
- width: "offsetWidth"
480
- };
481
- const equalize = (beforeEl, afterEl, type) => {
482
- const prop = types[type];
483
- const beforeSize = beforeEl[prop];
484
- const afterSize = afterEl[prop];
485
- if (Number.isInteger(beforeSize) && Number.isInteger(afterSize)) {
486
- const maxSize = `${Math.max(beforeSize, afterSize)}px`;
487
- beforeEl.style[type] = maxSize;
488
- afterEl.style[type] = maxSize;
489
- }
490
- };
491
- const withEqualBeforeAfter = (WrappedComponent) => {
492
- const displayName = WrappedComponent.displayName ?? WrappedComponent.name ?? "Component";
493
- const Enhanced = ({ equalBeforeAfter, direction, afterContent, beforeContent, ref, ...rest }) => {
494
- const internalRef = useRef(null);
495
- useImperativeHandle(ref, () => internalRef.current);
496
- useLayoutEffect(() => {
497
- if (!equalBeforeAfter || !beforeContent || !afterContent) return;
498
- if (!internalRef.current) return;
499
- const el = internalRef.current;
500
- const beforeEl = el.firstElementChild;
501
- const afterEl = el.lastElementChild;
502
- if (beforeEl && afterEl && beforeEl !== afterEl) equalize(beforeEl, afterEl, direction === "rows" ? "height" : "width");
503
- }, [
504
- equalBeforeAfter,
505
- beforeContent,
506
- afterContent,
507
- direction
508
- ]);
509
- return /* @__PURE__ */ jsx(WrappedComponent, {
510
- ...rest,
511
- afterContent,
512
- beforeContent,
513
- ref: internalRef
514
- });
515
- };
516
- Enhanced.displayName = `withEqualSizeBeforeAfter(${displayName})`;
517
- return Enhanced;
518
- };
519
-
520
499
  //#endregion
521
500
  //#region src/Element/index.ts
522
501
  var Element_default = Component$7;
@@ -706,108 +685,6 @@ Component$5.displayName = name$4;
706
685
  Component$5.pkgName = PKG_NAME;
707
686
  Component$5.VITUS_LABS__COMPONENT = name$4;
708
687
 
709
- //#endregion
710
- //#region src/List/withActiveState.tsx
711
- /**
712
- * HOC that adds single or multi selection state management to a list component.
713
- * Tracks which items are active via a scalar key (single mode) or a Map of
714
- * key-to-boolean entries (multi mode). Injects `itemProps` callback that
715
- * provides each item with `active`, `handleItemActive`, `toggleItemActive`,
716
- * and other selection helpers. Supports `activeItemRequired` to prevent
717
- * deselecting the last active item.
718
- */
719
- const RESERVED_KEYS = [
720
- "type",
721
- "activeItems",
722
- "itemProps",
723
- "activeItemRequired"
724
- ];
725
- const component = (WrappedComponent) => {
726
- const displayName = WrappedComponent.displayName || WrappedComponent.name || "Component";
727
- const Enhanced = (props) => {
728
- const { type = "single", activeItemRequired, activeItems, itemProps = {}, ...rest } = props;
729
- const initActiveItems = () => {
730
- if (type === "single") {
731
- if (!Array.isArray(activeItems)) return activeItems;
732
- } else if (type === "multi") {
733
- const activeItemsHelper = Array.isArray(activeItems) ? activeItems : [activeItems];
734
- return new Map(activeItemsHelper.map((id) => [id, true]));
735
- }
736
- };
737
- const [innerActiveItems, setActiveItems] = useState(initActiveItems());
738
- const countActiveItems = (data) => {
739
- let result = 0;
740
- data.forEach((value) => {
741
- if (value) result += 1;
742
- });
743
- return result;
744
- };
745
- const updateItemState = (key) => {
746
- if (type === "single") setActiveItems((prevState) => {
747
- if (activeItemRequired) return key;
748
- if (prevState === key) return void 0;
749
- return key;
750
- });
751
- else if (type === "multi") setActiveItems((prevState) => {
752
- const activeItems = new Map(prevState);
753
- if (activeItemRequired && activeItems.get(key) && countActiveItems(activeItems) === 1) return activeItems;
754
- activeItems.set(key, !activeItems.get(key));
755
- return activeItems;
756
- });
757
- else setActiveItems(void 0);
758
- };
759
- const handleItemActive = (key) => {
760
- updateItemState(key);
761
- };
762
- const updateAllItemsState = (status) => {
763
- if (!status) setActiveItems(/* @__PURE__ */ new Map());
764
- };
765
- const setItemActive = (key) => {
766
- updateItemState(key);
767
- };
768
- const unsetItemActive = (key) => {
769
- updateItemState(key);
770
- };
771
- const toggleItemActive = (key) => {
772
- updateItemState(key);
773
- };
774
- const unsetAllItemsActive = () => {
775
- updateAllItemsState(false);
776
- };
777
- const isItemActive = (key) => {
778
- if (!innerActiveItems) return false;
779
- if (type === "single") return innerActiveItems === key;
780
- if (type === "multi" && innerActiveItems instanceof Map) return !!innerActiveItems.get(key);
781
- return false;
782
- };
783
- const attachMultipleProps = { unsetAllItemsActive };
784
- const attachItemProps = (props) => {
785
- const { key } = props;
786
- return {
787
- ...typeof itemProps === "object" ? itemProps : itemProps(props),
788
- active: isItemActive(key),
789
- handleItemActive: () => handleItemActive(key),
790
- setItemActive,
791
- unsetItemActive,
792
- toggleItemActive,
793
- ...type === "multi" ? attachMultipleProps : {}
794
- };
795
- };
796
- useEffect(() => {
797
- if (type === "single" && Array.isArray(activeItems)) {
798
- if (process.env.NODE_ENV !== "production") console.warn("[@vitus-labs/elements] List/withActiveState: `activeItems` was passed as an array but `type` is \"single\". In single selection mode, `activeItems` should be a single key (string | number). The array value will be ignored.");
799
- }
800
- }, [type, activeItems]);
801
- return /* @__PURE__ */ jsx(WrappedComponent, {
802
- ...rest,
803
- itemProps: attachItemProps
804
- });
805
- };
806
- Enhanced.RESERVED_KEYS = RESERVED_KEYS;
807
- Enhanced.displayName = `@vitus-labs/elements/List/withActiveState(${displayName})`;
808
- return Enhanced;
809
- };
810
-
811
688
  //#endregion
812
689
  //#region src/List/index.ts
813
690
  var List_default = Component$5;
@@ -1452,5 +1329,5 @@ Component$1.VITUS_LABS__COMPONENT = name;
1452
1329
  var Util_default = Component$1;
1453
1330
 
1454
1331
  //#endregion
1455
- export { Element_default as Element, List_default as List, Overlay_default as Overlay, Component as OverlayProvider, Portal_default as Portal, Provider, Text_default as Text, Util_default as Util, useOverlay, component as withActiveState, withEqualBeforeAfter as withEqualSizeBeforeAfter };
1332
+ export { Element_default as Element, List_default as List, Overlay_default as Overlay, Component as OverlayProvider, Portal_default as Portal, Provider, Text_default as Text, Util_default as Util, useOverlay };
1456
1333
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  import { Provider, alignContent, extendCss, makeItResponsive, value } from "@vitus-labs/unistyle";
2
2
  import { config, context, isEmpty, omit, pick, render, throttle } from "@vitus-labs/core";
3
- import { Children, createContext, forwardRef, memo, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { Children, createContext, forwardRef, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { isFragment } from "react-is";
6
6
  import { createPortal } from "react-dom";
@@ -21,7 +21,7 @@ const IS_DEVELOPMENT = process.env.NODE_ENV !== "production";
21
21
  * equalCols flex distribution. The "content" slot gets `flex: 1` to
22
22
  * fill remaining space between before and after.
23
23
  */
24
- const { styled: styled$2, css: css$2, component: component$2 } = config;
24
+ const { styled: styled$2, css: css$2, component: component$1 } = config;
25
25
  const equalColsCSS = `
26
26
  flex: 1;
27
27
  `;
@@ -67,7 +67,7 @@ const styles$2 = ({ css, theme: t, rootSize }) => css`
67
67
 
68
68
  ${t.extraStyles && extendCss(t.extraStyles)};
69
69
  `;
70
- const StyledComponent = styled$2(component$2)`
70
+ const StyledComponent = styled$2(component$1)`
71
71
  ${""};
72
72
 
73
73
  display: flex;
@@ -140,7 +140,7 @@ var Content_default = component_default$1;
140
140
  * split flex behavior across two DOM nodes for button/fieldset/legend
141
141
  * elements where a single flex container is insufficient.
142
142
  */
143
- const { styled: styled$1, css: css$1, component: component$1 } = config;
143
+ const { styled: styled$1, css: css$1, component } = config;
144
144
  const childFixCSS = `
145
145
  display: flex;
146
146
  flex: 1;
@@ -168,7 +168,7 @@ const styles$1 = ({ theme: t, css }) => css`
168
168
  ${t.extraStyles && extendCss(t.extraStyles)};
169
169
  `;
170
170
  const platformCSS = `display: flex;`;
171
- var styled_default$1 = styled$1(component$1)`
171
+ var styled_default$1 = styled$1(component)`
172
172
  position: relative;
173
173
  ${platformCSS};
174
174
 
@@ -252,11 +252,26 @@ var Wrapper_default = Component$8;
252
252
  * like void elements (input, img) and inline elements (span, a) by
253
253
  * skipping children or switching sub-tags accordingly.
254
254
  */
255
+ const equalize = (el, direction) => {
256
+ const beforeEl = el.firstElementChild;
257
+ const afterEl = el.lastElementChild;
258
+ if (beforeEl && afterEl && beforeEl !== afterEl) {
259
+ const type = direction === "rows" ? "height" : "width";
260
+ const prop = type === "height" ? "offsetHeight" : "offsetWidth";
261
+ const beforeSize = beforeEl[prop];
262
+ const afterSize = afterEl[prop];
263
+ if (Number.isInteger(beforeSize) && Number.isInteger(afterSize)) {
264
+ const maxSize = `${Math.max(beforeSize, afterSize)}px`;
265
+ beforeEl.style[type] = maxSize;
266
+ afterEl.style[type] = maxSize;
267
+ }
268
+ }
269
+ };
255
270
  const defaultDirection = "inline";
256
271
  const defaultContentDirection = "rows";
257
272
  const defaultAlignX = "left";
258
273
  const defaultAlignY = "center";
259
- const Component$7 = forwardRef(({ innerRef, tag, label, content, children, beforeContent, afterContent, block, equalCols, gap, direction, alignX = defaultAlignX, alignY = defaultAlignY, css, contentCss, beforeContentCss, afterContentCss, contentDirection = defaultContentDirection, contentAlignX = defaultAlignX, contentAlignY = defaultAlignY, beforeContentDirection = defaultDirection, beforeContentAlignX = defaultAlignX, beforeContentAlignY = defaultAlignY, afterContentDirection = defaultDirection, afterContentAlignX = defaultAlignX, afterContentAlignY = defaultAlignY, ...props }, ref) => {
274
+ const Component$7 = forwardRef(({ innerRef, tag, label, content, children, beforeContent, afterContent, equalBeforeAfter, block, equalCols, gap, direction, alignX = defaultAlignX, alignY = defaultAlignY, css, contentCss, beforeContentCss, afterContentCss, contentDirection = defaultContentDirection, contentAlignX = defaultAlignX, contentAlignY = defaultAlignY, beforeContentDirection = defaultDirection, beforeContentAlignX = defaultAlignX, beforeContentAlignY = defaultAlignY, afterContentDirection = defaultDirection, afterContentAlignX = defaultAlignX, afterContentAlignY = defaultAlignY, ...props }, ref) => {
260
275
  const isSimpleElement = !beforeContent && !afterContent;
261
276
  const CHILDREN = children ?? content ?? label;
262
277
  const isInline = false;
@@ -285,8 +300,24 @@ const Component$7 = forwardRef(({ innerRef, tag, label, content, children, befor
285
300
  alignY,
286
301
  direction
287
302
  ]);
303
+ const equalizeRef = useRef(null);
304
+ const externalRef = ref ?? innerRef;
305
+ const mergedRef = useCallback((node) => {
306
+ equalizeRef.current = node;
307
+ if (typeof externalRef === "function") externalRef(node);
308
+ else if (externalRef != null) externalRef.current = node;
309
+ }, [externalRef]);
310
+ useLayoutEffect(() => {
311
+ if (!equalBeforeAfter || !beforeContent || !afterContent) return;
312
+ if (equalizeRef.current) equalize(equalizeRef.current, direction);
313
+ }, [
314
+ equalBeforeAfter,
315
+ beforeContent,
316
+ afterContent,
317
+ direction
318
+ ]);
288
319
  const WRAPPER_PROPS = {
289
- ref: ref ?? innerRef,
320
+ ref: mergedRef,
290
321
  extendCss: css,
291
322
  tag,
292
323
  block,
@@ -343,58 +374,6 @@ Component$7.displayName = name$5;
343
374
  Component$7.pkgName = PKG_NAME;
344
375
  Component$7.VITUS_LABS__COMPONENT = name$5;
345
376
 
346
- //#endregion
347
- //#region src/Element/withEqualSizeBeforeAfter.tsx
348
- /**
349
- * HOC that equalizes the dimensions of beforeContent and afterContent areas.
350
- * After render, it measures both DOM nodes via useLayoutEffect and sets the
351
- * larger dimension on both so they match. Uses width for inline direction
352
- * and height for rows direction. This is useful for centering the main
353
- * content when before/after slots have different intrinsic sizes.
354
- */
355
- const types = {
356
- height: "offsetHeight",
357
- width: "offsetWidth"
358
- };
359
- const equalize = (beforeEl, afterEl, type) => {
360
- const prop = types[type];
361
- const beforeSize = beforeEl[prop];
362
- const afterSize = afterEl[prop];
363
- if (Number.isInteger(beforeSize) && Number.isInteger(afterSize)) {
364
- const maxSize = `${Math.max(beforeSize, afterSize)}px`;
365
- beforeEl.style[type] = maxSize;
366
- afterEl.style[type] = maxSize;
367
- }
368
- };
369
- const withEqualBeforeAfter = (WrappedComponent) => {
370
- const displayName = WrappedComponent.displayName ?? WrappedComponent.name ?? "Component";
371
- const Enhanced = ({ equalBeforeAfter, direction, afterContent, beforeContent, ref, ...rest }) => {
372
- const internalRef = useRef(null);
373
- useImperativeHandle(ref, () => internalRef.current);
374
- useLayoutEffect(() => {
375
- if (!equalBeforeAfter || !beforeContent || !afterContent) return;
376
- if (!internalRef.current) return;
377
- const el = internalRef.current;
378
- const beforeEl = el.firstElementChild;
379
- const afterEl = el.lastElementChild;
380
- if (beforeEl && afterEl && beforeEl !== afterEl) equalize(beforeEl, afterEl, direction === "rows" ? "height" : "width");
381
- }, [
382
- equalBeforeAfter,
383
- beforeContent,
384
- afterContent,
385
- direction
386
- ]);
387
- return /* @__PURE__ */ jsx(WrappedComponent, {
388
- ...rest,
389
- afterContent,
390
- beforeContent,
391
- ref: internalRef
392
- });
393
- };
394
- Enhanced.displayName = `withEqualSizeBeforeAfter(${displayName})`;
395
- return Enhanced;
396
- };
397
-
398
377
  //#endregion
399
378
  //#region src/Element/index.ts
400
379
  var Element_default = Component$7;
@@ -584,108 +563,6 @@ Component$5.displayName = name$4;
584
563
  Component$5.pkgName = PKG_NAME;
585
564
  Component$5.VITUS_LABS__COMPONENT = name$4;
586
565
 
587
- //#endregion
588
- //#region src/List/withActiveState.tsx
589
- /**
590
- * HOC that adds single or multi selection state management to a list component.
591
- * Tracks which items are active via a scalar key (single mode) or a Map of
592
- * key-to-boolean entries (multi mode). Injects `itemProps` callback that
593
- * provides each item with `active`, `handleItemActive`, `toggleItemActive`,
594
- * and other selection helpers. Supports `activeItemRequired` to prevent
595
- * deselecting the last active item.
596
- */
597
- const RESERVED_KEYS = [
598
- "type",
599
- "activeItems",
600
- "itemProps",
601
- "activeItemRequired"
602
- ];
603
- const component = (WrappedComponent) => {
604
- const displayName = WrappedComponent.displayName || WrappedComponent.name || "Component";
605
- const Enhanced = (props) => {
606
- const { type = "single", activeItemRequired, activeItems, itemProps = {}, ...rest } = props;
607
- const initActiveItems = () => {
608
- if (type === "single") {
609
- if (!Array.isArray(activeItems)) return activeItems;
610
- } else if (type === "multi") {
611
- const activeItemsHelper = Array.isArray(activeItems) ? activeItems : [activeItems];
612
- return new Map(activeItemsHelper.map((id) => [id, true]));
613
- }
614
- };
615
- const [innerActiveItems, setActiveItems] = useState(initActiveItems());
616
- const countActiveItems = (data) => {
617
- let result = 0;
618
- data.forEach((value) => {
619
- if (value) result += 1;
620
- });
621
- return result;
622
- };
623
- const updateItemState = (key) => {
624
- if (type === "single") setActiveItems((prevState) => {
625
- if (activeItemRequired) return key;
626
- if (prevState === key) return void 0;
627
- return key;
628
- });
629
- else if (type === "multi") setActiveItems((prevState) => {
630
- const activeItems = new Map(prevState);
631
- if (activeItemRequired && activeItems.get(key) && countActiveItems(activeItems) === 1) return activeItems;
632
- activeItems.set(key, !activeItems.get(key));
633
- return activeItems;
634
- });
635
- else setActiveItems(void 0);
636
- };
637
- const handleItemActive = (key) => {
638
- updateItemState(key);
639
- };
640
- const updateAllItemsState = (status) => {
641
- if (!status) setActiveItems(/* @__PURE__ */ new Map());
642
- };
643
- const setItemActive = (key) => {
644
- updateItemState(key);
645
- };
646
- const unsetItemActive = (key) => {
647
- updateItemState(key);
648
- };
649
- const toggleItemActive = (key) => {
650
- updateItemState(key);
651
- };
652
- const unsetAllItemsActive = () => {
653
- updateAllItemsState(false);
654
- };
655
- const isItemActive = (key) => {
656
- if (!innerActiveItems) return false;
657
- if (type === "single") return innerActiveItems === key;
658
- if (type === "multi" && innerActiveItems instanceof Map) return !!innerActiveItems.get(key);
659
- return false;
660
- };
661
- const attachMultipleProps = { unsetAllItemsActive };
662
- const attachItemProps = (props) => {
663
- const { key } = props;
664
- return {
665
- ...typeof itemProps === "object" ? itemProps : itemProps(props),
666
- active: isItemActive(key),
667
- handleItemActive: () => handleItemActive(key),
668
- setItemActive,
669
- unsetItemActive,
670
- toggleItemActive,
671
- ...type === "multi" ? attachMultipleProps : {}
672
- };
673
- };
674
- useEffect(() => {
675
- if (type === "single" && Array.isArray(activeItems)) {
676
- if (process.env.NODE_ENV !== "production") console.warn("[@vitus-labs/elements] List/withActiveState: `activeItems` was passed as an array but `type` is \"single\". In single selection mode, `activeItems` should be a single key (string | number). The array value will be ignored.");
677
- }
678
- }, [type, activeItems]);
679
- return /* @__PURE__ */ jsx(WrappedComponent, {
680
- ...rest,
681
- itemProps: attachItemProps
682
- });
683
- };
684
- Enhanced.RESERVED_KEYS = RESERVED_KEYS;
685
- Enhanced.displayName = `@vitus-labs/elements/List/withActiveState(${displayName})`;
686
- return Enhanced;
687
- };
688
-
689
566
  //#endregion
690
567
  //#region src/List/index.ts
691
568
  var List_default = Component$5;
@@ -1328,5 +1205,5 @@ Component$1.VITUS_LABS__COMPONENT = name;
1328
1205
  var Util_default = Component$1;
1329
1206
 
1330
1207
  //#endregion
1331
- export { Element_default as Element, List_default as List, Overlay_default as Overlay, Component as OverlayProvider, Portal_default as Portal, Provider, Text_default as Text, Util_default as Util, useOverlay, component as withActiveState, withEqualBeforeAfter as withEqualSizeBeforeAfter };
1208
+ export { Element_default as Element, List_default as List, Overlay_default as Overlay, Component as OverlayProvider, Portal_default as Portal, Provider, Text_default as Text, Util_default as Util, useOverlay };
1332
1209
  //# sourceMappingURL=vitus-labs-elements.native.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitus-labs/elements",
3
- "version": "1.4.3-alpha.3+16703b4",
3
+ "version": "1.4.3-alpha.5+d1944da",
4
4
  "license": "MIT",
5
5
  "author": "Vit Bokisch <vit@bokisch.cz>",
6
6
  "maintainers": [
@@ -61,15 +61,15 @@
61
61
  "react-dom": ">= 19"
62
62
  },
63
63
  "devDependencies": {
64
- "@vitus-labs/core": "1.4.3-alpha.3+16703b4",
65
- "@vitus-labs/rocketstyle": "1.4.3-alpha.3+16703b4",
64
+ "@vitus-labs/core": "1.4.3-alpha.5+d1944da",
65
+ "@vitus-labs/rocketstyle": "1.4.3-alpha.5+d1944da",
66
66
  "@vitus-labs/tools-rolldown": "^1.6.0",
67
67
  "@vitus-labs/tools-storybook": "^1.6.0",
68
68
  "@vitus-labs/tools-typescript": "^1.6.0",
69
- "@vitus-labs/unistyle": "1.4.3-alpha.3+16703b4"
69
+ "@vitus-labs/unistyle": "1.4.3-alpha.5+d1944da"
70
70
  },
71
71
  "dependencies": {
72
72
  "react-is": "^19.2.3"
73
73
  },
74
- "gitHead": "16703b4c8dc0525bd504c531aeb082bf593579cc"
74
+ "gitHead": "d1944da60503895137a81218faa237e5a9213b66"
75
75
  }